CGEM BOSS 6.6.5.i
BESIII Offline Software System
Loading...
Searching...
No Matches
XmlRpcDispatch.cpp
Go to the documentation of this file.
1
2#include "XmlRpcDispatch.h"
3#include "XmlRpcSource.h"
4#include "XmlRpcUtil.h"
5
6#include <math.h>
7#include <sys/timeb.h>
8
9#if defined(_WINDOWS)
10# include <winsock2.h>
11
12# define USE_FTIME
13# if defined(_MSC_VER)
14# define timeb _timeb
15# define ftime _ftime
16# endif
17#else
18# include <sys/time.h>
19#endif // _WINDOWS
20
21#include <iostream>
22
23using namespace XmlRpc;
24
25
27{
28 _endTime = -1.0;
29 _doClear = false;
30 _inWork = false;
31}
32
33
37
38// Monitor this source for the specified events and call its event handler
39// when the event occurs
40void
42{
43 _sources.push_back(MonitoredSource(source, mask));
44}
45
46// Stop monitoring this source. Does not close the source.
47void
49{
50 for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
51 if (it->getSource() == source)
52 {
53 _sources.erase(it);
54 break;
55 }
56}
57
58
59// Modify the types of events to watch for on this source
60void
62{
63 for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
64 if (it->getSource() == source)
65 {
66 it->getMask() = eventMask;
67 break;
68 }
69}
70
71
72
73// Watch current set of sources and process events
74void
75XmlRpcDispatch::work(double timeout)
76{
77 // Compute end time
78 _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout);
79 _doClear = false;
80 _inWork = true;
81
82 // Only work while there is something to monitor
83 while (_sources.size() > 0) {
84
85 // Construct the sets of descriptors we are interested in
86 fd_set inFd, outFd, excFd;
87 FD_ZERO(&inFd);
88 FD_ZERO(&outFd);
89 FD_ZERO(&excFd);
90
91 int maxFd = -1; // Not used on windows
92 SourceList::iterator it;
93 for (it=_sources.begin(); it!=_sources.end(); ++it) {
94 int fd = it->getSource()->getfd();
95 if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd);
96 if (it->getMask() & WritableEvent) FD_SET(fd, &outFd);
97 if (it->getMask() & Exception) FD_SET(fd, &excFd);
98 if (it->getMask() && fd > maxFd) maxFd = fd;
99 }
100
101 // Check for events
102 int nEvents;
103 if (timeout < 0.0)
104 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL);
105 else
106 {
107 struct timeval tv;
108 tv.tv_sec = (int)floor(timeout);
109 tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000;
110 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv);
111 }
112
113 if (nEvents < 0)
114 {
115 XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
116 _inWork = false;
117 return;
118 }
119
120 // Process events
121 for (it=_sources.begin(); it != _sources.end(); )
122 {
123 SourceList::iterator thisIt = it++;
124 XmlRpcSource* src = thisIt->getSource();
125 int fd = src->getfd();
126 unsigned newMask = (unsigned) -1;
127 if (fd <= maxFd) {
128 // If you select on multiple event types this could be ambiguous
129 if (FD_ISSET(fd, &inFd))
130 newMask &= src->handleEvent(ReadableEvent);
131 if (FD_ISSET(fd, &outFd))
132 newMask &= src->handleEvent(WritableEvent);
133 if (FD_ISSET(fd, &excFd))
134 newMask &= src->handleEvent(Exception);
135
136 if ( ! newMask) {
137 _sources.erase(thisIt); // Stop monitoring this one
138 if ( ! src->getKeepOpen())
139 src->close();
140 } else if (newMask != (unsigned) -1) {
141 thisIt->getMask() = newMask;
142 }
143 }
144 }
145
146 // Check whether to clear all sources
147 if (_doClear)
148 {
149 SourceList closeList = _sources;
150 _sources.clear();
151 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) {
152 XmlRpcSource *src = it->getSource();
153 src->close();
154 }
155
156 _doClear = false;
157 }
158
159 // Check whether end time has passed
160 if (0 <= _endTime && getTime() > _endTime){
161 std::cout<< "XmlRpc : time out when connect to database " << std::endl;//yzhang debug
162 break;
163 }
164 }
165
166 _inWork = false;
167}
168
169
170// Exit from work routine. Presumably this will be called from
171// one of the source event handlers.
172void
174{
175 _endTime = 0.0; // Return from work asap
176}
177
178// Clear all sources from the monitored sources list
179void
181{
182 if (_inWork)
183 _doClear = true; // Finish reporting current events before clearing
184 else
185 {
186 SourceList closeList = _sources;
187 _sources.clear();
188 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it)
189 it->getSource()->close();
190 }
191}
192
193
194double
196{
197#ifdef USE_FTIME
198 struct timeb tbuff;
199
200 ftime(&tbuff);
201 return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) +
202 ((double) tbuff.timezone * 60));
203#else
204 struct timeval tv;
205 struct timezone tz;
206
207 gettimeofday(&tv, &tz);
208 return (tv.tv_sec + tv.tv_usec / 1000000.0);
209#endif /* USE_FTIME */
210}
211
212
void removeSource(XmlRpcSource *source)
@ ReadableEvent
data available to read
@ WritableEvent
connected/data can be written without blocking
void work(double msTime)
void exit()
Exit from work routine.
std::list< MonitoredSource > SourceList
void clear()
Clear all sources from the monitored sources list. Sources are closed.
void setSourceEvents(XmlRpcSource *source, unsigned eventMask)
Modify the types of events to watch for on this source.
void addSource(XmlRpcSource *source, unsigned eventMask)
An RPC source represents a file descriptor to monitor.
virtual void close()
Close the owned fd. If deleteOnClose was specified at construction, the object is deleted.
int getfd() const
Return the file descriptor being monitored.
bool getKeepOpen() const
Return whether the file descriptor should be kept open if it is no longer monitored.
virtual unsigned handleEvent(unsigned eventType)=0
Return true to continue monitoring this source.
static void error(const char *fmt,...)
Dump error messages somewhere.