BOSS 8.0.0
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
26 _endTime = -1.0;
27 _doClear = false;
28 _inWork = false;
29}
30
32
33// Monitor this source for the specified events and call its event handler
34// when the event occurs
35void XmlRpcDispatch::addSource( XmlRpcSource* source, unsigned mask ) {
36 _sources.push_back( MonitoredSource( source, mask ) );
37}
38
39// Stop monitoring this source. Does not close the source.
41 for ( SourceList::iterator it = _sources.begin(); it != _sources.end(); ++it )
42 if ( it->getSource() == source )
43 {
44 _sources.erase( it );
45 break;
46 }
47}
48
49// Modify the types of events to watch for on this source
50void XmlRpcDispatch::setSourceEvents( XmlRpcSource* source, unsigned eventMask ) {
51 for ( SourceList::iterator it = _sources.begin(); it != _sources.end(); ++it )
52 if ( it->getSource() == source )
53 {
54 it->getMask() = eventMask;
55 break;
56 }
57}
58
59// Watch current set of sources and process events
60void XmlRpcDispatch::work( double timeout ) {
61 // Compute end time
62 _endTime = ( timeout < 0.0 ) ? -1.0 : ( getTime() + timeout );
63 _doClear = false;
64 _inWork = true;
65
66 // Only work while there is something to monitor
67 while ( _sources.size() > 0 )
68 {
69
70 // Construct the sets of descriptors we are interested in
71 fd_set inFd, outFd, excFd;
72 FD_ZERO( &inFd );
73 FD_ZERO( &outFd );
74 FD_ZERO( &excFd );
75
76 int maxFd = -1; // Not used on windows
77 SourceList::iterator it;
78 for ( it = _sources.begin(); it != _sources.end(); ++it )
79 {
80 int fd = it->getSource()->getfd();
81 if ( it->getMask() & ReadableEvent ) FD_SET( fd, &inFd );
82 if ( it->getMask() & WritableEvent ) FD_SET( fd, &outFd );
83 if ( it->getMask() & Exception ) FD_SET( fd, &excFd );
84 if ( it->getMask() && fd > maxFd ) maxFd = fd;
85 }
86
87 // Check for events
88 int nEvents;
89 if ( timeout < 0.0 ) nEvents = select( maxFd + 1, &inFd, &outFd, &excFd, NULL );
90 else
91 {
92 struct timeval tv;
93 tv.tv_sec = (int)floor( timeout );
94 tv.tv_usec = ( (int)floor( 1000000.0 * ( timeout - floor( timeout ) ) ) ) % 1000000;
95 nEvents = select( maxFd + 1, &inFd, &outFd, &excFd, &tv );
96 }
97
98 if ( nEvents < 0 )
99 {
100 XmlRpcUtil::error( "Error in XmlRpcDispatch::work: error in select (%d).", nEvents );
101 _inWork = false;
102 return;
103 }
104
105 // Process events
106 for ( it = _sources.begin(); it != _sources.end(); )
107 {
108 SourceList::iterator thisIt = it++;
109 XmlRpcSource* src = thisIt->getSource();
110 int fd = src->getfd();
111 unsigned newMask = (unsigned)-1;
112 if ( fd <= maxFd )
113 {
114 // If you select on multiple event types this could be ambiguous
115 if ( FD_ISSET( fd, &inFd ) ) newMask &= src->handleEvent( ReadableEvent );
116 if ( FD_ISSET( fd, &outFd ) ) newMask &= src->handleEvent( WritableEvent );
117 if ( FD_ISSET( fd, &excFd ) ) newMask &= src->handleEvent( Exception );
118
119 if ( !newMask )
120 {
121 _sources.erase( thisIt ); // Stop monitoring this one
122 if ( !src->getKeepOpen() ) src->close();
123 }
124 else if ( newMask != (unsigned)-1 ) { thisIt->getMask() = newMask; }
125 }
126 }
127
128 // Check whether to clear all sources
129 if ( _doClear )
130 {
131 SourceList closeList = _sources;
132 _sources.clear();
133 for ( SourceList::iterator it = closeList.begin(); it != closeList.end(); ++it )
134 {
135 XmlRpcSource* src = it->getSource();
136 src->close();
137 }
138
139 _doClear = false;
140 }
141
142 // Check whether end time has passed
143 if ( 0 <= _endTime && getTime() > _endTime )
144 {
145 std::cout << "XmlRpc : time out when connect to database " << std::endl; // yzhang
146 // debug
147 break;
148 }
149 }
150
151 _inWork = false;
152}
153
154// Exit from work routine. Presumably this will be called from
155// one of the source event handlers.
157 _endTime = 0.0; // Return from work asap
158}
159
160// Clear all sources from the monitored sources list
162 if ( _inWork ) _doClear = true; // Finish reporting current events before clearing
163 else
164 {
165 SourceList closeList = _sources;
166 _sources.clear();
167 for ( SourceList::iterator it = closeList.begin(); it != closeList.end(); ++it )
168 it->getSource()->close();
169 }
170}
171
173#ifdef USE_FTIME
174 struct timeb tbuff;
175
176 ftime( &tbuff );
177 return ( (double)tbuff.time + ( (double)tbuff.millitm / 1000.0 ) +
178 ( (double)tbuff.timezone * 60 ) );
179#else
180 struct timeval tv;
181 struct timezone tz;
182
183 gettimeofday( &tv, &tz );
184 return ( tv.tv_sec + tv.tv_usec / 1000000.0 );
185#endif /* USE_FTIME */
186}
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()
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.