Example #1
0
void XmlRpcDispatch::processFds (short revents, SourceList::iterator thisIt, XmlRpcSource *chunkWait)
{
	XmlRpcSource* src = thisIt->getSource();
	unsigned newMask = (unsigned) -1;
	// If you select on multiple event types this could be ambiguous
	try
	{
		if (revents & (POLLIN | POLLPRI))
			newMask &= (src == chunkWait) ? src->handleChunkEvent(ReadableEvent) : src->handleEvent(ReadableEvent);
	}
	catch (const XmlRpcAsynchronous &async)
	{
		XmlRpcUtil::log(3, "Asynchronous event while handling response.");
		// stop monitoring the source..
		thisIt->getMask() = 0;
		src->goAsync ();
	}

	if (revents & POLLOUT)
		newMask &= (src == chunkWait) ? src->handleChunkEvent(WritableEvent) : src->handleEvent(WritableEvent);
	if (revents & (POLLRDHUP | POLLERR | POLLHUP | POLLNVAL))
		newMask &= (src == chunkWait) ? src->handleChunkEvent(Exception) : src->handleEvent(Exception);

	if ( ! newMask)
	{
		// Stop monitoring this one
		_sources.erase(thisIt);
		if ( ! src->getKeepOpen())
			src->close();
	}
	else if (newMask != (unsigned) -1)
	{
		thisIt->getMask() = newMask;
	}
}
Example #2
0
// Watch current set of sources and process events
void
XmlRpcDispatch::work(double timeoutSeconds)
{
  // Compute end time
  double timeNow = getTime();
  _endTime = (timeoutSeconds < 0.0) ? -1.0 : (timeNow + timeoutSeconds);
  _doClear = false;
  _inWork = true;

  // Only work while there is something to monitor
  while (_sources.size() > 0) {

    // Wait for and dispatch events
    if ( ! waitForAndProcessEvents(timeoutSeconds))
    {
      _inWork = false;
      return;
    }


    // Check whether to clear all sources
    if (_doClear)
    {
      SourceList sourcesToClose;
      _sources.swap(sourcesToClose);
      for (SourceList::iterator it=sourcesToClose.begin(); it!=sourcesToClose.end(); ++it)
      {
        XmlRpcSource *src = it->getSource();
        src->close();
      }

      _doClear = false;
    }

    // Check whether end time has passed or exit has been called
    if (_endTime == 0.0)        // Exit
    {
      break;
    }
    else if (_endTime > 0.0)    // Check for timeout
    {
      double t = getTime();
      if (t > _endTime)
        break;

      // Decrement timeout by elapsed time
      timeoutSeconds -= (t - timeNow);
      if (timeoutSeconds < 0.0) 
        timeoutSeconds = 0.0;    // Shouldn't happen but its fp math...
      timeNow = t;
    }
  }

  _inWork = false;
}
Example #3
0
// Watch current set of sources and process events
void XmlRpcDispatch::work(double timeout_ms, XmlRpcClient *chunkWait)
{
	// Compute end time
	_endTime = (timeout_ms < 0.0) ? -1.0 : (getTime() + timeout_ms/1000.0);
	_doClear = false;
	_inWork = true;

	if (chunkWait)
	{
		setSourceEvents(chunkWait, ReadableEvent | WritableEvent | Exception);
	}

	// Only work while there is something to monitor
	while (_sources.size() > 0)
	{

		// Construct the sets of descriptors we are interested in
		struct pollfd fds[MAX_POLLS];
		nfds_t nfds = 0;

		addToFds (fds, nfds);
		fds[nfds].fd = -1;

		// Check for events
		int nEvents;
		if (timeout_ms < 0.0)
			nEvents = poll(fds, nfds, 0);
		else
		{
			struct timespec tv;
			tv.tv_sec = (int) floor (timeout_ms / 1000.0);
			tv.tv_nsec = (int) (fmod (timeout_ms, 1000.0) * 1000000.0);
			nEvents = ppoll(fds, nfds, &tv, NULL);
		}

		if (nEvents < 0)
		{
			XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
			_inWork = false;
			return;
		}

		checkFds (fds, nfds, chunkWait);

		// Check whether to clear all sources
		if (_doClear)
		{
			SourceList closeList = _sources;
			_sources.clear();
			for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it)
			{
				XmlRpcSource *src = it->getSource();
				src->close();
			}

			_doClear = false;
		}

		// Check whether end time has passed
		if (0 <= _endTime && getTime() > _endTime)
			break;

		// if chunkWait and the connection received chunk..
		if (chunkWait && chunkWait->gotChunk ())
			break;
	}

	_inWork = false;
}
Example #4
0
// Watch current set of sources and process events
void
XmlRpcDispatch::work(double timeout)
{
  // Compute end time
  _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout);
  _doClear = false;
  _inWork = true;

  // Only work while there is something to monitor
  while (_sources.size() > 0) {

    // Construct the sets of descriptors we are interested in
    fd_set inFd, outFd, excFd;
	  FD_ZERO(&inFd);
	  FD_ZERO(&outFd);
	  FD_ZERO(&excFd);

    int maxFd = -1;     // Not used on windows
    SourceList::iterator it;
    for (it=_sources.begin(); it!=_sources.end(); ++it) {
      int fd = it->getSource()->getfd();
      if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd);
      if (it->getMask() & WritableEvent) FD_SET(fd, &outFd);
      if (it->getMask() & Exception)     FD_SET(fd, &excFd);
      if (it->getMask() && fd > maxFd)   maxFd = fd;
    }

    // Check for events
    int nEvents;
    if (timeout < 0.0)
      nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL);
    else 
    {
      struct timeval tv;
      tv.tv_sec = (int)floor(timeout);
      tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000;
      nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv);
    }

    if (nEvents < 0)
    {
      XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
      _inWork = false;
      return;
    }

    // Process events
    for (it=_sources.begin(); it != _sources.end(); )
    {
      SourceList::iterator thisIt = it++;
      XmlRpcSource* src = thisIt->getSource();
      int fd = src->getfd();
      unsigned newMask = (unsigned) -1;
      if (fd <= maxFd) {
        // If you select on multiple event types this could be ambiguous
        if (FD_ISSET(fd, &inFd))
          newMask &= src->handleEvent(ReadableEvent);
        if (FD_ISSET(fd, &outFd))
          newMask &= src->handleEvent(WritableEvent);
        if (FD_ISSET(fd, &excFd))
          newMask &= src->handleEvent(Exception);

        if ( ! newMask) {
          _sources.erase(thisIt);  // Stop monitoring this one
          if ( ! src->getKeepOpen())
            src->close();
        } else if (newMask != (unsigned) -1) {
          thisIt->getMask() = newMask;
        }
      }
    }

    // Check whether to clear all sources
    if (_doClear)
    {
      SourceList closeList = _sources;
      _sources.clear();
      for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) {
	XmlRpcSource *src = it->getSource();
        src->close();
      }

      _doClear = false;
    }

    // Check whether end time has passed
    if (0 <= _endTime && getTime() > _endTime)
      break;
  }

  _inWork = false;
}
Example #5
0
// Wait for I/O on any source, timeout, or interrupt signal.
bool
XmlRpcDispatch::waitForAndProcessEvents(double timeoutSeconds)
{
  // Construct the sets of descriptors we are interested in
  fd_set inFd, outFd, excFd;
  FD_ZERO(&inFd);
  FD_ZERO(&outFd);
  FD_ZERO(&excFd);

  XmlRpcSocket::Socket maxFd = 0;
  for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
  {
    XmlRpcSocket::Socket fd = it->getSource()->getfd();
    if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd);
    if (it->getMask() & WritableEvent) FD_SET(fd, &outFd);
    if (it->getMask() & Exception)     FD_SET(fd, &excFd);
    if (it->getMask() && fd > maxFd)   maxFd = fd;
  }

  // Check for events
  int nEvents;
  if (_endTime < 0.0)
  {
    nEvents = select(int(maxFd+1), &inFd, &outFd, &excFd, NULL);
  }
  else 
  {
    struct timeval tv;
    tv.tv_sec = (int)floor(timeoutSeconds);
    tv.tv_usec = ((int)floor(1000000.0 * (timeoutSeconds-floor(timeoutSeconds)))) % 1000000;
    nEvents = select(int(maxFd+1), &inFd, &outFd, &excFd, &tv);
  }

  if (nEvents < 0 && errno != EINTR)
  {
    XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
    return false;
  }

  // Process events. Copy source list to avoid invalidating iterator by removing sources.
  SourceList s(_sources);
  for (SourceList::iterator it=s.begin(); it != s.end(); ++it)
  {
    XmlRpcSource* src = it->getSource();
    XmlRpcSocket::Socket fd = src->getfd();

    if (fd <= maxFd)
    {
      // handleEvent is called once per event type signalled
      unsigned newMask = 0;
      int nset = 0;
      if (FD_ISSET(fd, &inFd))
      {
        newMask |= src->handleEvent(ReadableEvent);
        ++nset;
      }
      if (FD_ISSET(fd, &outFd))
      {
        newMask |= src->handleEvent(WritableEvent);
        ++nset;
      }
      if (FD_ISSET(fd, &excFd))
      {
        newMask |= src->handleEvent(Exception);
        ++nset;
      }

      // Some event occurred
      if (nset)
      {
        // This bit is not terribly efficient if many connections are active...
        if (newMask)
        {
          setSourceEvents(src, newMask);
        }
        else       // Stop monitoring this one
        {
          removeSource(src);

          if ( ! src->getKeepOpen())
            src->close();
        }
      }
    }
  }

  return true;
}
// Watch current set of sources and process events
void
XmlRpcDispatch::work(double timeout_in_seconds)
{
  // Compute end time
    _endTime = (timeout_in_seconds < 0.0) ? -1.0 : (getTime() + timeout_in_seconds);
  _doClear = false;
  _inWork = true;

  // Only work while there is something to monitor
  while (_sources.size() > 0) {
      // // Construct the sets of descriptors we are interested in
      // fd_set inFd, outFd, excFd;
      //       FD_ZERO(&inFd);
      //       FD_ZERO(&outFd);
      //       FD_ZERO(&excFd);

      //    int maxFd = -1;     // Not used on windows
      //    SourceList::iterator it;
    int fds_size = _sources.size();
    std::vector<struct pollfd> fds(fds_size);

    {

        int __offset = 0;
        for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
        {
            fds[__offset].fd = it->getSource()->getfd();
            fds[__offset].events = 0;
            fds[__offset].revents = 0;
            if (it->getMask() & ReadableEvent) fds[__offset].events |= POLLIN;
            if (it->getMask() & WritableEvent) fds[__offset].events |= POLLOUT;
            if (it->getMask() & Exception)     fds[__offset].events |= POLLERR;
            //  2      if (it->getMask() && fd > maxFd)   maxFd = fd;
            ++__offset;
        }
    }

    // Check for events
    returnhereoninterruptedsyscall:
    int nEvents;
    if (timeout_in_seconds < 0.0)
        nEvents = poll(&fds[0], fds_size, -1);
    else
    {
        nEvents = poll(&fds[0],fds_size, timeout_in_seconds * 1000);
    }
    if(nEvents == -1 and errno == EINTR)
        goto returnhereoninterruptedsyscall;

    if (nEvents < 0)
    {
        LOG_ERROR("Error in XmlRpcDispatch::work: error in select " <<  strerror(errno));
       //        LOG_ERROR(strerror(errno));

//        XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
        _inWork = false;
        return;
    }

    // Process events
    {

        size_t __offset = 0;

        for (SourceList::iterator it = _sources.begin(); it != _sources.end(); )
        {
            SourceList::iterator thisIt = it++;
            XmlRpcSource* src = thisIt->getSource();
            unsigned newMask = (unsigned) -1;

            // accepting a new connection (XmlRpcServer::handleEvent)
            // will add a new entry to _sources but we don't have an
            // entry in the fds around.
            if (__offset < fds.size())
            {
                assert(fds[__offset].fd == src->getfd());
                // if (fd <= maxFd)
                // {
                // If you select on multiple event types this could be ambiguous
                if (fds[__offset].revents bitand POLLIN)
                {
                    newMask &= src->handleEvent(ReadableEvent);
                }
                if (fds[__offset].revents bitand POLLOUT)
                {
                    newMask &= src->handleEvent(WritableEvent);
                }
                if (fds[__offset].revents bitand POLLERR)
                {
                    newMask &= src->handleEvent(Exception);
                }
            }

            if (newMask == 0)
            {
                _sources.erase(thisIt);  // Stop monitoring this one
                if (!src->getKeepOpen())
                {
                    src->close();
                }

            }
            else if (newMask != (unsigned) -1)
            {
                thisIt->getMask() = newMask;
            }
            __offset++;
        }
    }

    // Check whether to clear all sources
    if (_doClear)
    {
      SourceList closeList = _sources;
      _sources.clear();
      for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) {
	XmlRpcSource *src = it->getSource();
        src->close();
      }

      _doClear = false;
    }

    // Check whether end time has passed
    if (0 <= _endTime && getTime() > _endTime)
      break;
  }

  _inWork = false;
}