Go to the documentation of this file.00001
00002 #include "XmlRpcDispatch.h"
00003 #include "XmlRpcSource.h"
00004 #include "XmlRpcUtil.h"
00005
00006 #include <math.h>
00007 #include <errno.h>
00008 #include <sys/timeb.h>
00009
00010 #if defined(_WINDOWS)
00011 # include <winsock2.h>
00012
00013 # define USE_FTIME
00014 # if defined(_MSC_VER)
00015 # define timeb _timeb
00016 # define ftime _ftime_s
00017 # endif
00018 #else
00019 # include <sys/time.h>
00020 #endif // _WINDOWS
00021
00022
00023 using namespace XmlRpc;
00024
00025
00026 XmlRpcDispatch::XmlRpcDispatch()
00027 {
00028 _endTime = -1.0;
00029 _doClear = false;
00030 _inWork = false;
00031 }
00032
00033
00034 XmlRpcDispatch::~XmlRpcDispatch()
00035 {
00036 }
00037
00038
00039
00040 void
00041 XmlRpcDispatch::addSource(XmlRpcSource* source, unsigned mask)
00042 {
00043 _sources.push_back(MonitoredSource(source, mask));
00044 }
00045
00046
00047 void
00048 XmlRpcDispatch::removeSource(XmlRpcSource* source)
00049 {
00050 for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
00051 if (it->getSource() == source)
00052 {
00053 _sources.erase(it);
00054 break;
00055 }
00056 }
00057
00058
00059
00060 void
00061 XmlRpcDispatch::setSourceEvents(XmlRpcSource* source, unsigned eventMask)
00062 {
00063 for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
00064 if (it->getSource() == source)
00065 {
00066 it->getMask() = eventMask;
00067 break;
00068 }
00069 }
00070
00071
00072
00073
00074 void
00075 XmlRpcDispatch::work(double timeout)
00076 {
00077
00078 _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout);
00079 _doClear = false;
00080 _inWork = true;
00081
00082
00083 while (_sources.size() > 0) {
00084
00085
00086 fd_set inFd, outFd, excFd;
00087 FD_ZERO(&inFd);
00088 FD_ZERO(&outFd);
00089 FD_ZERO(&excFd);
00090
00091 int maxFd = -1;
00092 SourceList::iterator it;
00093 for (it=_sources.begin(); it!=_sources.end(); ++it) {
00094 int fd = it->getSource()->getfd();
00095 if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd);
00096 if (it->getMask() & WritableEvent) FD_SET(fd, &outFd);
00097 if (it->getMask() & Exception) FD_SET(fd, &excFd);
00098 if (it->getMask() && fd > maxFd) maxFd = fd;
00099 }
00100
00101
00102 int nEvents;
00103 if (timeout < 0.0)
00104 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL);
00105 else
00106 {
00107 struct timeval tv;
00108 tv.tv_sec = (int)floor(timeout);
00109 tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000;
00110 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv);
00111 }
00112
00113 if (nEvents < 0)
00114 {
00115 if(errno != EINTR)
00116 XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
00117 _inWork = false;
00118 return;
00119 }
00120
00121
00122 for (it=_sources.begin(); it != _sources.end(); )
00123 {
00124 SourceList::iterator thisIt = it++;
00125 XmlRpcSource* src = thisIt->getSource();
00126 int fd = src->getfd();
00127 unsigned newMask = (unsigned) -1;
00128 if (fd <= maxFd) {
00129
00130 if (FD_ISSET(fd, &inFd))
00131 newMask &= src->handleEvent(ReadableEvent);
00132 if (FD_ISSET(fd, &outFd))
00133 newMask &= src->handleEvent(WritableEvent);
00134 if (FD_ISSET(fd, &excFd))
00135 newMask &= src->handleEvent(Exception);
00136
00137
00138
00139
00140 for (thisIt=_sources.begin(); thisIt != _sources.end(); thisIt++)
00141 {
00142 if(thisIt->getSource() == src)
00143 break;
00144 }
00145 if(thisIt == _sources.end())
00146 {
00147 XmlRpcUtil::error("Error in XmlRpcDispatch::work: couldn't find source iterator");
00148 continue;
00149 }
00150
00151 if ( ! newMask) {
00152 _sources.erase(thisIt);
00153 if ( ! src->getKeepOpen())
00154 src->close();
00155 } else if (newMask != (unsigned) -1) {
00156 thisIt->getMask() = newMask;
00157 }
00158 }
00159 }
00160
00161
00162 if (_doClear)
00163 {
00164 SourceList closeList = _sources;
00165 _sources.clear();
00166 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) {
00167 XmlRpcSource *src = it->getSource();
00168 src->close();
00169 }
00170
00171 _doClear = false;
00172 }
00173
00174
00175 if (0 <= _endTime && getTime() > _endTime)
00176 break;
00177 }
00178
00179 _inWork = false;
00180 }
00181
00182
00183
00184
00185 void
00186 XmlRpcDispatch::exit()
00187 {
00188 _endTime = 0.0;
00189 }
00190
00191
00192 void
00193 XmlRpcDispatch::clear()
00194 {
00195 if (_inWork)
00196 _doClear = true;
00197 else
00198 {
00199 SourceList closeList = _sources;
00200 _sources.clear();
00201 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it)
00202 it->getSource()->close();
00203 }
00204 }
00205
00206
00207 double
00208 XmlRpcDispatch::getTime()
00209 {
00210 #ifdef USE_FTIME
00211 struct timeb tbuff;
00212
00213 ftime(&tbuff);
00214 return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) +
00215 ((double) tbuff.timezone * 60));
00216 #else
00217 struct timeval tv;
00218 struct timezone tz;
00219
00220 gettimeofday(&tv, &tz);
00221 return (tv.tv_sec + tv.tv_usec / 1000000.0);
00222 #endif
00223 }
00224
00225