/**
 * Process all active socket requests.
 *
 * This is called under the server thread or server AO.
 *
 * @param aSelect(output): True if we need to do another Select call.
 * @param aNfds(output): Value = 1 + maximum socket handle for all sockets
 *    that we are monitoring with the select call.
 */
void OsclSocketServI::ProcessSocketRequests(bool &aSelect, int &aNfds)
{
    //process all active requests

    aSelect = false;
    TOsclSocket maxsocket = 0;
    aNfds = (int)maxsocket + 1;

    // Pick up new requests from the app thread.
    iSockServRequestList.Lock();
    {
        iSockServRequestList.GetNewRequests();

        //flush any data on the loopback socket.
        iLoopbackSocket.Read();
    }
    iSockServRequestList.Unlock();

    if (iSockServRequestList.iActiveRequests.empty())
    {
        //nothing to do!
        return;
    }

    //Make a pass through the open request list and cancel or process each request.
    uint32 i;
    for (i = 0;i < iSockServRequestList.iActiveRequests.size();i++)
    {
        OsclSocketServRequestQElem* elem = &iSockServRequestList.iActiveRequests[i];

        if (elem->iCancel)
        {
            //Request was canceled
            elem->iSocketRequest->Complete(elem, OSCL_REQUEST_ERR_CANCEL);
        }
        else if (!IsServConnected())
        {
            //Server died or was closed.
            elem->iSocketRequest->Complete(elem, OSCL_REQUEST_ERR_GENERAL
                                           , (iServError) ? iServError : PVSOCK_ERR_SERV_NOT_CONNECTED);
        }
        else
        {
            //These routines will start the request, or else process
            //the results of prior select call, and also set the select
            //flags for the next call.

            elem->iSelect = 0;

            switch (elem->iSocketRequest->Fxn())
            {
                case EPVSocketShutdown:
                    elem->iSocketRequest->iSocketI->ProcessShutdown(elem);
                    break;

                case EPVSocketConnect:
                    elem->iSocketRequest->iSocketI->ProcessConnect(elem);
                    break;

                case EPVSocketAccept:
                    elem->iSocketRequest->iSocketI->ProcessAccept(elem);
                    break;

                case EPVSocketSend:
                    elem->iSocketRequest->iSocketI->ProcessSend(elem);
                    break;

                case EPVSocketSendTo:
                    elem->iSocketRequest->iSocketI->ProcessSendTo(elem);
                    break;

                case EPVSocketRecv:
                    elem->iSocketRequest->iSocketI->ProcessRecv(elem);
                    break;

                case EPVSocketRecvFrom:
                    elem->iSocketRequest->iSocketI->ProcessRecvFrom(elem);
                    break;

                default:
                    OSCL_ASSERT(0);
                    break;
            }
        }
    }

    //Zero out any old select set
    FD_ZERO(&iReadset);
    FD_ZERO(&iWriteset);
    FD_ZERO(&iExceptset);
    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Clearing select set"));

    //Now make a pass to either delete the request or collate the select flags.
    for (i = 0;i < iSockServRequestList.iActiveRequests.size();)
    {
        OsclSocketServRequestQElem* elem = &iSockServRequestList.iActiveRequests[i];

        if (elem->iSocketRequest)
        {
            //request is still active
            i++;

            if (elem->iSelect > 0)
            {
                //Need to do a select call for this socket

                if (!aSelect)
                    aSelect = true;

                TOsclSocket osock = elem->iSocketRequest->iSocketI->Socket();

                if (osock > maxsocket)
                {
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Maxsocket to %d", osock));
                    maxsocket = osock;
                }

                //Add the socket to the select set.  Keep in mind there can be multiple requests
                //per socket, so check whether the socket is already added before adding.

                if ((elem->iSelect & OSCL_READSET_FLAG) == OSCL_READSET_FLAG
                        && !(FD_ISSET(osock, &iReadset)))
                {
                    FD_SET(osock, &iReadset);
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Readset for %d", osock));
                }

                if ((elem->iSelect & OSCL_WRITESET_FLAG) == OSCL_WRITESET_FLAG
                        && !(FD_ISSET(osock, &iWriteset)))
                {
                    FD_SET(osock, &iWriteset);
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Writeset for %d", osock));
                }

                if ((elem->iSelect & OSCL_EXCEPTSET_FLAG) == OSCL_EXCEPTSET_FLAG
                        && !(FD_ISSET(osock, &iExceptset)))
                {
                    FD_SET(osock, &iExceptset);
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Exceptset for %d", osock));
                }
            }
        }
        else
        {
            //request is complete and can be deleted.
            iSockServRequestList.iActiveRequests.erase(elem);
        }
    }

    //also monitor the loopback socket if we're going to call select.
    iLoopbackSocket.ProcessSelect(aSelect, maxsocket);

    if (aSelect)
    {
        aNfds = (int)(maxsocket + 1);
    }
    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Select %d, NFDS %d", aSelect, aNfds));
}
void OsclSocketServI::ProcessSocketRequests()
#endif
{
    //process all active requests

#if PV_SOCKET_SERVER_SELECT
    //keep track of max socket handle to monitor.
    TOsclSocket maxsocket = 0;
    aNfds = (int)maxsocket + 1;

    //save input handle count, then clear it until the next select operation.
    int nhandles = aNhandles;
    aNhandles = 0;
#endif

    // Pick up new requests from the app thread.
    START_SERVI_STATS2(EServiProc_Queue);
    iSockServRequestList.Lock();
    {
        iSockServRequestList.GetNewRequests();

#if PV_SOCKET_SERVER_SELECT_LOOPBACK_SOCKET
        //flush any data on the loopback socket.
        iLoopbackSocket.Read();
#endif
    }
    iSockServRequestList.Unlock();
    END_SERVI_STATS2(EServiProc_Queue);

    if (iSockServRequestList.iActiveRequests.empty())
    {
        //nothing to do!
        return;
    }

    //Make a pass through the open request list and cancel or process each request.
    START_SERVI_STATS2(EServiProc_Loop);
    uint32 i;
    for (i = 0; i < iSockServRequestList.iActiveRequests.size(); i++)
    {
        OsclSocketServRequestQElem* elem = &iSockServRequestList.iActiveRequests[i];

        if (elem->iCancel)
        {
            //Request was canceled
            START_SERVI_STATS2(EServiProcLoop_Cancel);
            elem->iSocketRequest->Complete(elem, OSCL_REQUEST_ERR_CANCEL);
            END_SERVI_STATS2(EServiProcLoop_Cancel);
        }
        else if (!IsServConnected())
        {
            //Server died or was closed.
            START_SERVI_STATS2(EServiProcLoop_Closed);
            elem->iSocketRequest->Complete(elem, OSCL_REQUEST_ERR_GENERAL
                                           , (iServError) ? iServError : PVSOCK_ERR_SERV_NOT_CONNECTED);
            END_SERVI_STATS2(EServiProcLoop_Closed);
        }
#if PV_SOCKET_SERVER_SELECT
        else if (nhandles == 0 && elem->iSelect)
        {
            //we're monitoring this socket but there is no current
            //socket activity-- just keep waiting.
            ;
        }
#endif
        else
        {
            //These routines will start the request, or else process
            //the results of prior select call, and also set the select
            //flags for the next call.

            switch (elem->iSocketRequest->Fxn())
            {
                case EPVSocketShutdown:
                    START_SERVI_STATS2(EServiProcLoop_Shutdown);
                    elem->iSocketRequest->iSocketI->ProcessShutdown(elem);
                    END_SERVI_STATS2(EServiProcLoop_Shutdown);
                    break;

                case EPVSocketConnect:
                    START_SERVI_STATS2(EServiProcLoop_Connect);
                    elem->iSocketRequest->iSocketI->ProcessConnect(elem);
                    END_SERVI_STATS2(EServiProcLoop_Connect);
                    break;

                case EPVSocketAccept:
                    START_SERVI_STATS2(EServiProcLoop_Accept);
                    elem->iSocketRequest->iSocketI->ProcessAccept(elem);
                    END_SERVI_STATS2(EServiProcLoop_Accept);
                    break;

                case EPVSocketSend:
                    START_SERVI_STATS2(EServiProcLoop_Send);
                    elem->iSocketRequest->iSocketI->ProcessSend(elem);
                    END_SERVI_STATS2(EServiProcLoop_Send);
                    break;

                case EPVSocketSendTo:
                    START_SERVI_STATS2(EServiProcLoop_SendTo);
                    elem->iSocketRequest->iSocketI->ProcessSendTo(elem);
                    END_SERVI_STATS2(EServiProcLoop_SendTo);
                    break;

                case EPVSocketRecv:
                    START_SERVI_STATS2(EServiProcLoop_Recv);
                    elem->iSocketRequest->iSocketI->ProcessRecv(elem);
                    END_SERVI_STATS2(EServiProcLoop_Recv);
                    break;

                case EPVSocketRecvFrom:
                    START_SERVI_STATS2(EServiProcLoop_RecvFrom);
                    elem->iSocketRequest->iSocketI->ProcessRecvFrom(elem);
                    END_SERVI_STATS2(EServiProcLoop_RecvFrom);
                    break;

                default:
                    OSCL_ASSERT(0);
                    break;
            }
        }
    }
    END_SERVI_STATS2(EServiProc_Loop);

    //Zero out any old select set
    START_SERVI_STATS2(EServiProc_Fdset);
#if PV_SOCKET_SERVER_SELECT
    FD_ZERO(&iReadset);
    FD_ZERO(&iWriteset);
    FD_ZERO(&iExceptset);
#endif
    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Clearing select set"));

    //Now make a pass to either delete the request or collate the select flags.
    for (i = 0; i < iSockServRequestList.iActiveRequests.size();)
    {
        OsclSocketServRequestQElem* elem = &iSockServRequestList.iActiveRequests[i];

        if (elem->iSocketRequest)
        {
            //request is still active
            i++;

#if PV_SOCKET_SERVER_SELECT
            if (elem->iSelect > 0)
            {
                //Need to do a select call for this socket

                TOsclSocket osock = elem->iSocketRequest->iSocketI->Socket();

                if (osock > maxsocket)
                {
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Maxsocket to %d", osock));
                    maxsocket = osock;
                }

                //Add the socket to the select set.  Keep in mind there can be multiple requests
                //per socket, so check whether the socket is already added before adding.

                if ((elem->iSelect & OSCL_READSET_FLAG) == OSCL_READSET_FLAG
                        && !(FD_ISSET(osock, &iReadset)))
                {
                    FD_SET(osock, &iReadset);
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Readset for %d", osock));
                }

                if ((elem->iSelect & OSCL_WRITESET_FLAG) == OSCL_WRITESET_FLAG
                        && !(FD_ISSET(osock, &iWriteset)))
                {
                    FD_SET(osock, &iWriteset);
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Writeset for %d", osock));
                }

                if ((elem->iSelect & OSCL_EXCEPTSET_FLAG) == OSCL_EXCEPTSET_FLAG
                        && !(FD_ISSET(osock, &iExceptset)))
                {
                    FD_SET(osock, &iExceptset);
                    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests Setting Exceptset for %d", osock));
                }
            }
#endif
        }
        else
        {
            //request is complete and can be deleted.
            iSockServRequestList.iActiveRequests.erase(elem);
        }
    }
    END_SERVI_STATS2(EServiProc_Fdset);

#if PV_SOCKET_SERVER_SELECT
    if (maxsocket)
    {
#if PV_SOCKET_SERVER_SELECT_LOOPBACK_SOCKET
        //also monitor the loopback socket if we're going to call select.
        iLoopbackSocket.ProcessSelect(maxsocket);
#endif

        //set Nfds to 1+maxsocket handle.
        aNfds = (int)maxsocket + 1;
    }

    LOGSERV((0, "OsclSocketServI::ProcessSocketRequests NFDS %d", aNfds));
#endif

}