// 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; }
// Clear all sources from the monitored sources list void XmlRpcDispatch::clear() { if (_inWork) _doClear = true; // Finish reporting current events before clearing else { SourceList closeList = _sources; _sources.clear(); for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) it->getSource()->close(); } }
// Clear all sources from the monitored sources list void XmlRpcDispatch::clear() { if (_inWork) { _doClear = true; // Finish reporting current events before clearing } else { SourceList sourcesToClose; _sources.swap(sourcesToClose); for (SourceList::iterator it=sourcesToClose.begin(); it!=sourcesToClose.end(); ++it) it->getSource()->close(); } }
/** \fn FillData::Run(SourceList &sourcelist) * \brief Goes through the sourcelist and updates its channels with * program info grabbed with the associated grabber. * \return true if there were no failures */ bool FillData::Run(SourceList &sourcelist) { SourceList::iterator it; SourceList::iterator it2; QString status, querystr; MSqlQuery query(MSqlQuery::InitCon()); QDateTime GuideDataBefore, GuideDataAfter; int failures = 0; int externally_handled = 0; int total_sources = sourcelist.size(); int source_channels = 0; QString sidStr = QString("Updating source #%1 (%2) with grabber %3"); need_post_grab_proc = false; int nonewdata = 0; bool has_dd_source = false; // find all DataDirect duplicates, so we only data download once. for (it = sourcelist.begin(); it != sourcelist.end(); ++it) { if (!is_grabber_datadirect((*it).xmltvgrabber)) continue; has_dd_source = true; for (it2 = sourcelist.begin(); it2 != sourcelist.end(); ++it2) { if (((*it).id != (*it2).id) && ((*it).xmltvgrabber == (*it2).xmltvgrabber) && ((*it).userid == (*it2).userid) && ((*it).password == (*it2).password)) { (*it).dd_dups.push_back((*it2).id); } } } if (has_dd_source) ddprocessor.CreateTempDirectory(); for (it = sourcelist.begin(); it != sourcelist.end(); ++it) { if (!fatalErrors.empty()) break; query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0;"); query.bindValue(":SRCID", (*it).id); if (query.exec() && query.size() > 0) { query.next(); if (!query.isNull(0)) GuideDataBefore = QDateTime::fromString(query.value(0).toString(), Qt::ISODate); } channel_update_run = false; endofdata = false; QString xmltv_grabber = (*it).xmltvgrabber; if (xmltv_grabber == "eitonly") { LOG(VB_GENERAL, LOG_INFO, QString("Source %1 configured to use only the " "broadcasted guide data. Skipping.") .arg((*it).id)); externally_handled++; updateLastRunStart(query); updateLastRunEnd(query); continue; } else if (xmltv_grabber.trimmed().isEmpty() || xmltv_grabber == "/bin/true" || xmltv_grabber == "none") { LOG(VB_GENERAL, LOG_INFO, QString("Source %1 configured with no grabber. Nothing to do.") .arg((*it).id)); externally_handled++; updateLastRunStart(query); updateLastRunEnd(query); continue; } LOG(VB_GENERAL, LOG_INFO, sidStr.arg((*it).id) .arg((*it).name) .arg(xmltv_grabber)); query.prepare( "SELECT COUNT(chanid) FROM channel WHERE sourceid = " ":SRCID AND xmltvid != ''"); query.bindValue(":SRCID", (*it).id); if (query.exec() && query.size() > 0) { query.next(); source_channels = query.value(0).toInt(); if (source_channels > 0) { LOG(VB_GENERAL, LOG_INFO, QString("Found %1 channels for source %2 which use grabber") .arg(source_channels).arg((*it).id)); } else { LOG(VB_GENERAL, LOG_INFO, QString("No channels are configured to use grabber.")); } } else { source_channels = 0; LOG(VB_GENERAL, LOG_INFO, QString("Can't get a channel count for source id %1") .arg((*it).id)); } bool hasprefmethod = false; if (is_grabber_external(xmltv_grabber)) { uint flags = kMSRunShell | kMSStdOut | kMSBuffered; MythSystem grabber_capabilities_proc(xmltv_grabber, QStringList("--capabilities"), flags); grabber_capabilities_proc.Run(25); if (grabber_capabilities_proc.Wait() != GENERIC_EXIT_OK) LOG(VB_GENERAL, LOG_ERR, QString("%1 --capabilities failed or we timed out waiting." " You may need to upgrade your xmltv grabber") .arg(xmltv_grabber)); else { QByteArray result = grabber_capabilities_proc.ReadAll(); QTextStream ostream(result); QString capabilities; while (!ostream.atEnd()) { QString capability = ostream.readLine().simplified(); if (capability.isEmpty()) continue; capabilities += capability + ' '; if (capability == "baseline") (*it).xmltvgrabber_baseline = true; if (capability == "manualconfig") (*it).xmltvgrabber_manualconfig = true; if (capability == "cache") (*it).xmltvgrabber_cache = true; if (capability == "preferredmethod") hasprefmethod = true; } LOG(VB_GENERAL, LOG_INFO, QString("Grabber has capabilities: %1") .arg(capabilities)); } } if (hasprefmethod) { uint flags = kMSRunShell | kMSStdOut | kMSBuffered; MythSystem grabber_method_proc(xmltv_grabber, QStringList("--preferredmethod"), flags); grabber_method_proc.Run(15); if (grabber_method_proc.Wait() != GENERIC_EXIT_OK) LOG(VB_GENERAL, LOG_ERR, QString("%1 --preferredmethod failed or we timed out " "waiting. You may need to upgrade your xmltv " "grabber").arg(xmltv_grabber)); else { QTextStream ostream(grabber_method_proc.ReadAll()); (*it).xmltvgrabber_prefmethod = ostream.readLine().simplified(); LOG(VB_GENERAL, LOG_INFO, QString("Grabber prefers method: %1") .arg((*it).xmltvgrabber_prefmethod)); } } need_post_grab_proc |= !is_grabber_datadirect(xmltv_grabber); if (is_grabber_datadirect(xmltv_grabber) && dd_grab_all) { if (only_update_channels) DataDirectUpdateChannels(*it); else { QDate qCurrentDate = QDate::currentDate(); if (!GrabData(*it, 0, &qCurrentDate)) ++failures; } } else if ((*it).xmltvgrabber_prefmethod == "allatonce") { if (!GrabData(*it, 0)) ++failures; } else if ((*it).xmltvgrabber_baseline || is_grabber_datadirect(xmltv_grabber)) { QDate qCurrentDate = QDate::currentDate(); // We'll keep grabbing until it returns nothing // Max days currently supported is 21 int grabdays = (is_grabber_datadirect(xmltv_grabber)) ? 14 : REFRESH_MAX; grabdays = (maxDays > 0) ? maxDays : grabdays; grabdays = (only_update_channels) ? 1 : grabdays; vector<bool> refresh_request; refresh_request.resize(grabdays, refresh_all); for (int i = 0; i < refresh_day.size(); i++) refresh_request[i] = refresh_day[i]; if (is_grabber_datadirect(xmltv_grabber) && only_update_channels) { DataDirectUpdateChannels(*it); grabdays = 0; } for (int i = 0; i < grabdays; i++) { if (!fatalErrors.empty()) break; // We need to check and see if the current date has changed // since we started in this loop. If it has, we need to adjust // the value of 'i' to compensate for this. if (QDate::currentDate() != qCurrentDate) { QDate newDate = QDate::currentDate(); i += (newDate.daysTo(qCurrentDate)); if (i < 0) i = 0; qCurrentDate = newDate; } QString prevDate(qCurrentDate.addDays(i-1).toString()); QString currDate(qCurrentDate.addDays(i).toString()); LOG(VB_GENERAL, LOG_INFO, ""); // add a space between days LOG(VB_GENERAL, LOG_INFO, "Checking day @ " + QString("offset %1, date: %2").arg(i).arg(currDate)); bool download_needed = false; if (refresh_request[i]) { if ( i == 1 ) { LOG(VB_GENERAL, LOG_INFO, "Data Refresh always needed for tomorrow"); } else { LOG(VB_GENERAL, LOG_INFO, "Data Refresh needed because of user request"); } download_needed = true; } else { // Check to see if we already downloaded data for this date. querystr = "SELECT c.chanid, COUNT(p.starttime) " "FROM channel c " "LEFT JOIN program p ON c.chanid = p.chanid " " AND starttime >= " "DATE_ADD(DATE_ADD(CURRENT_DATE(), " "INTERVAL '%1' DAY), INTERVAL '20' HOUR) " " AND starttime < DATE_ADD(CURRENT_DATE(), " "INTERVAL '%2' DAY) " "WHERE c.sourceid = %3 AND c.xmltvid != '' " "GROUP BY c.chanid;"; if (query.exec(querystr.arg(i-1).arg(i).arg((*it).id)) && query.isActive()) { int prevChanCount = 0; int currentChanCount = 0; int previousDayCount = 0; int currentDayCount = 0; LOG(VB_CHANNEL, LOG_INFO, QString("Checking program counts for day %1") .arg(i-1)); while (query.next()) { if (query.value(1).toInt() > 0) prevChanCount++; previousDayCount += query.value(1).toInt(); LOG(VB_CHANNEL, LOG_INFO, QString(" chanid %1 -> %2 programs") .arg(query.value(0).toString()) .arg(query.value(1).toInt())); } if (query.exec(querystr.arg(i).arg(i+1).arg((*it).id)) && query.isActive()) { LOG(VB_CHANNEL, LOG_INFO, QString("Checking program counts for day %1") .arg(i)); while (query.next()) { if (query.value(1).toInt() > 0) currentChanCount++; currentDayCount += query.value(1).toInt(); LOG(VB_CHANNEL, LOG_INFO, QString(" chanid %1 -> %2 programs") .arg(query.value(0).toString()) .arg(query.value(1).toInt())); } } else { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh because we are unable to " "query the data for day %1 to " "determine if we have enough").arg(i)); download_needed = true; } if (currentChanCount < (prevChanCount * 0.90)) { LOG(VB_GENERAL, LOG_INFO, QString("Data refresh needed because only %1 " "out of %2 channels have at least one " "program listed for day @ offset %3 " "from 8PM - midnight. Previous day " "had %4 channels with data in that " "time period.") .arg(currentChanCount).arg(source_channels) .arg(i).arg(prevChanCount)); download_needed = true; } else if (currentDayCount == 0) { LOG(VB_GENERAL, LOG_INFO, QString("Data refresh needed because no data " "exists for day @ offset %1 from 8PM - " "midnight.").arg(i)); download_needed = true; } else if (previousDayCount == 0) { LOG(VB_GENERAL, LOG_INFO, QString("Data refresh needed because no data " "exists for day @ offset %1 from 8PM - " "midnight. Unable to calculate how " "much we should have for the current " "day so a refresh is being forced.") .arg(i-1)); download_needed = true; } else if (currentDayCount < (currentChanCount * 3)) { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh needed because offset " "day %1 has less than 3 programs " "per channel for the 8PM - midnight " "time window for channels that " "normally have data. " "We want at least %2 programs, but " "only found %3") .arg(i).arg(currentChanCount * 3) .arg(currentDayCount)); download_needed = true; } else if (currentDayCount < (previousDayCount / 2)) { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh needed because offset " "day %1 has less than half the number " "of programs as the previous day for " "the 8PM - midnight time window. " "We want at least %2 programs, but " "only found %3").arg(i) .arg(previousDayCount / 2) .arg(currentDayCount)); download_needed = true; } } else { LOG(VB_GENERAL, LOG_INFO, QString("Data Refresh needed because we are unable " "to query the data for day @ offset %1 to " "determine how much we should have for " "offset day %2.").arg(i-1).arg(i)); download_needed = true; } } if (download_needed) { LOG(VB_GENERAL, LOG_NOTICE, QString("Refreshing data for ") + currDate); if (!GrabData(*it, i, &qCurrentDate)) { ++failures; if (!fatalErrors.empty() || interrupted) { break; } } if (endofdata) { LOG(VB_GENERAL, LOG_INFO, "Grabber is no longer returning program data, " "finishing"); break; } } else { LOG(VB_GENERAL, LOG_NOTICE, QString("Data is already present for ") + currDate + ", skipping"); } } if (!fatalErrors.empty()) break; } else { LOG(VB_GENERAL, LOG_ERR, QString("Grabbing XMLTV data using ") + xmltv_grabber + " is not supported. You may need to upgrade to" " the latest version of XMLTV."); } if (interrupted) { break; } query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c " "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID " "AND manualid = 0;"); query.bindValue(":SRCID", (*it).id); if (query.exec() && query.size() > 0) { query.next(); if (!query.isNull(0)) GuideDataAfter = QDateTime::fromString( query.value(0).toString(), Qt::ISODate); } if (GuideDataAfter == GuideDataBefore) { nonewdata++; } } if (!fatalErrors.empty()) { for (int i = 0; i < fatalErrors.size(); i++) { LOG(VB_GENERAL, LOG_CRIT, LOC + "Encountered Fatal Error: " + fatalErrors[i]); } return false; } if (only_update_channels && !need_post_grab_proc) return true; if (failures == 0) { if (nonewdata > 0 && (total_sources != externally_handled)) status = QString(QObject::tr( "mythfilldatabase ran, but did not insert " "any new data into the Guide for %1 of %2 sources. " "This can indicate a potential grabber failure.")) .arg(nonewdata) .arg(total_sources); else status = QObject::tr("Successful."); updateLastRunStatus(query, status); } return (failures == 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; }
// 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; }
bool AcquireImages() { // Create a GEV Device finder dialog PvDeviceFinderWnd lDeviceFinderWnd; // Prompt the user to select a GEV Device lDeviceFinderWnd.ShowModal(); // Get the connectivity information for the selected GEV Device PvDeviceInfo* lDeviceInfo = lDeviceFinderWnd.GetSelected(); // If no device is selected, abort if( lDeviceInfo == NULL ) { cout << "No device selected." << endl; return false; } PvString lMACAddress = lDeviceInfo->GetMACAddress(); PvString lIPAddress = lDeviceInfo->GetIPAddress(); // Connect to the GEV Device PvDevice lDevice; cout << "Connecting to " << lMACAddress.GetAscii() << endl; // if ( !lDevice.Connect( lDeviceInfo ).IsOK() ) if ( !lDevice.Connect( lDeviceInfo ).IsOK() ) { cout << "Unable to connect to " << lMACAddress.GetAscii() << endl; return false; } cout << "Successfully connected to " << lMACAddress.GetAscii() << endl; cout << endl; SourceList lSources; // Get source selector PvGenEnum *lSourceSelector = lDevice.GetGenParameters()->GetEnum( "SourceSelector" ); if ( lSourceSelector != NULL ) { // Go through all sources, create source objects PvInt64 lCount = 0; lSourceSelector->GetEntriesCount( lCount ); for ( PvInt64 i = 0; i < lCount; i++ ) { // Get source enum entry const PvGenEnumEntry *lEE = NULL; lSourceSelector->GetEntryByIndex( i, &lEE ); // If available, create source if ( ( lEE != NULL ) && lEE->IsAvailable() ) { // Get source name PvString lSourceName; lEE->GetName( lSourceName ); // Create source Source *lSource = new Source( &lDevice, lIPAddress, lSourceName ); lSource->Open(); // Add to sources list lSources.push_back( lSource ); cout << endl; } } } else { // If no source selector, just create a single source Source *lSource = new Source( &lDevice, lIPAddress, "" ); lSource->Open(); // Add to sources list lSources.push_back( lSource ); cout << endl; } // Start the acquisiton on all sources SourceList::iterator lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *( lIt++ ) )->StartAcquisition(); cout << endl; } // Aggressive initial value, will be adjusted vs frame rate PvUInt32 lTimeout = 1; // Acquire images until the user instructs us to stop cout << "<press a key to stop streaming>" << endl; while ( !PvKbHit() ) { double lNewTimeout = 1000.0; lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *lIt )->RetrieveImages( lTimeout ); ( *lIt )->PrintStatistics(); // Always use the smallest recommended timeout double lRecommendedTimeout = ( *lIt )->GetRecommendedTimeout(); if ( lRecommendedTimeout < lNewTimeout ) { lNewTimeout = lRecommendedTimeout; } lIt++; } // Update timeout for next round - smallest recommended divided by number of sources lTimeout = static_cast<PvUInt32>( lNewTimeout / static_cast<double>( lSources.size() ) + 0.5 ); cout << "\r"; } PvGetChar(); // Flush key buffer for next stop cout << endl << endl; // Stop the acquisiton on all sources lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *( lIt++ ) )->StopAcquisition(); cout << endl; } // Close and delete sources lIt = lSources.begin(); while ( lIt != lSources.end() ) { ( *lIt )->Close(); cout << endl; delete *lIt; lIt++; } // Finally disconnect the device. Optional, still nice to have cout << "Disconnecting device" << endl; lDevice.Disconnect(); 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; }