source: trunk/MagicSoft/Control/SubsystemIO/Subsystem.plain.H@ 1052

Last change on this file since 1052 was 1041, checked in by casaldaliga, 23 years ago
First release
File size: 10.9 KB
Line 
1#ifndef SUBSYSTEM
2#define SUBSYSTEM
3
4#include "PeriodicAction.H"
5#include "TCPListener.H"
6#include "PeriodicAction.H"
7#include "TCPSender.H"
8#define TIMESTAMP_LEN 12
9//%02.2d:%02.2d:%02.2d:%03.3d
10//in Makefile#define MAXMSG 4096
11/**
12 * Base class for MAGIC Subsystem's communication with CC
13 *
14 * It implements commandListener (see MAGIC-TDAS 00-07) as a TCPListener
15 * derived class, to be able to custom the behaviour by overriding its
16 * methods
17 *
18 * Missing properties: Special Report in a GenerateSpecialReport method, also
19 * a final implementation of CheckReportAcknowledge (CC sends back
20 * "RECV:timestamp", with timestamp the one extracted from subsystem
21 * report. So subsystem has to have a member lastReportTimestamp to compare).
22 * Timeout in CheckReportAcknowledge?????.
23 *
24 * @short Base class for MAGIC Subsystem's communication with CC
25 * @author Marc Casaldaliga
26 * @version 0.9
27 * @see TCPListener
28 */
29class Subsystem: public TCPListener
30{
31
32public:
33
34 /**
35 * Set the string to be sent in the next report that will be sent to
36 * CC (with timestamp but without protocol specific item,
37 * e.g. trailing \n). The timestamp is the data one, the time when
38 * data was taken (the relevant for analysis), nothing to do with the
39 * the time the report will be sent.
40 *
41 * It takes care internally of suspending and resuming communications
42 * not to send something is being modified etc
43 *
44 * @param report CString with pure report (without "\n" ...)
45 */
46 void SetReportString(char * report);
47
48 /**
49 * Class unique constructor with the parameters which specify
50 * Subsystem configuration.
51 *
52 * @param portCommandListener TCP/IP port Subsystem will open to
53 * listen to cc commands
54 *
55 * @param reportPeriod Aproximate (+- 500ms) time in microsec,
56 * between each report is sent to CC
57 *
58 * @param ccName C string with CC machine name
59 *
60 * @param portReportListener TCP/IP port opened in CC which Subsystem
61 * will contact to send reports
62 *
63 * @param maxTimeoutCount_. Times subsystem tries to reconnect CC
64 * (with reportPeriod) periodicity, before it considers CC not
65 * available. After this count is reached Subsystem has to react some
66 * way (parking itself, ...). This is done by
67 * Subsystem::HandleConnectionTimeoutIsOver
68 *
69 * @param specialReportOnStartup When connection with CC is
70 * stablished for first time after a Subsystem startup a special
71 * report to CC with subsystem setup must be sent to ensure any setup
72 * changes (which may have happened while CC was down) are
73 * recorded. This C string only contains report content without any
74 * protocol dependent character
75 *
76 * @see #HandleConnectionTimeoutIsOver
77 *
78 */
79 Subsystem (unsigned short int portCommandListener, unsigned long int
80 reportPeriod, char * ccName, unsigned short int
81 portReportListener, unsigned short int maxTimeoutCount_, char *
82 specialReportOnStartup );
83
84 /**
85 * Send (immediately) a special report which a part from
86 * protocol specific items (e.g. trailing \n and special report
87 * identifier) contains the argument specialReport
88 *
89 * ??? timestamp ????
90 *
91 * It takes care internally of suspending and resuming communications
92 * not to send something is being modified etc
93 *
94 * @param specialReport CString with pure special report (without
95 * "\n" ...)
96 *
97 * @return Returns whether sending will be succesful (true) or not
98 * (false)
99 */
100 bool SendSpecialReportContaining(char * specialReport);
101
102 /**
103 * Blocks main thread until Subsystem::Shutdown is called
104 */
105 void WaitingForShutdown();
106
107 /**
108 * Subsystem communications will be shutdown definitely. Call this
109 * inside ProcessCmd or HandleConnectionTimeoutIsOver when your
110 * subsystem has to be stopped. If you only want to go standalone but
111 * still in contact with CC, you have to Ulock it but not this.
112 *
113 * This call unblocks WaitingForShutdown in main, so your subsystem
114 * application can finish.
115 */
116 void Shutdown();
117
118protected:
119 /**
120 * Field with the report that will be sent to CC (with timestamp but
121 * without protocol specific item, e.g. trailing \n)
122 *
123 * To be modified only within GenerateReport
124 */
125 char reportString[MAXMSG];
126
127 /** To be overriden. It has to do all the job of interpreting CC
128 * commands: (not the ones
129 * regarding starting connection, locking ...) but the ones for the
130 * subsystem function (This way we separate the protocol dependent
131 * stuff).
132 *
133 * Compares Subsystem::ccCmd with known commands from cc and executes
134 * the appropiate function
135 *
136 * This method is automatically called when a command from cc is
137 * received, after checking it is not a communication/locking command
138 *
139 * If receiving a nonsense command call to ResetConnectionToCC()
140 * (Network partner it's not -a properly working- CC). In principle
141 * this will close and open again, but let's leave it this way so that
142 * it is not protocol dependent
143 *
144 * @param ccCmd CString with pure CC command (without "\n" ...)
145 */
146 virtual void ProcessCmd(char *ccCmd);
147
148 /** GenerateReport (to be overriden) This next method is automatically
149 * called before sending a report.
150 *
151 * According to state and data this should write
152 * Subsystem::reportString (it
153 * should include the timestamp of the data sent, but without any
154 * trailing \n--this is part of the protocol)
155 *
156 * After it, this Subsystem::reportString plus any protocol dependent
157 * thing is sent. This GenerateReport and send is periodically
158 * repeated with reportPeriod
159 *
160 * Alternatively, one may leave GenerateReport empty and from outside
161 * call to Subsystem::SetReportString when hardware info is updated
162 * (probably what one what like to do).
163 */
164 virtual void GenerateReport();
165
166 /** HandleConnectionTimeoutIsOver. Does what the subsystem is suposed
167 * to do when it has lost definitely connection to CC. To be
168 * overriden.
169 *
170 * After Subsystem::maxTimeoutCount times of reconnection tries CC is
171 * considered not available. Subsystem has to react some way (parking
172 * itself, ... ) depending on its autonomy. This is done by
173 * overriding this method with the desired behaviour.
174 *
175 * After HandleConnectionTimeoutIsOver is done Subsystem will listen
176 * to CC again and start all communication process.
177 *
178 * see #maxTimeoutCount
179 */
180 virtual void HandleConnectionTimeoutIsOver();
181
182 /** SuspendComm. Suspend communication threads
183 *
184 * To prevent Subsystem to access its resources (e.g. send
185 * reportString) when we are about to access them externally (fill
186 * reportString with actual data), one can call to this method and
187 * suspend subsystem activity.
188 * To resume it call to Subsystem::ResumeComm.
189 *
190 * Always paired with a ResumeComm.
191 *
192 * If Subsystem is at that time accessing the resources, SuspendComm
193 * will wait for them to be released and then will lock them.
194 *
195 * @see #ResumeComm
196 *
197 */
198 void SuspendComm();
199
200 /** ResumeComm. Resume communication threads
201 *
202 * After calling SuspendComm() and having access to Subsystem
203 * resources (e.g. fill reportString with actual data) allow
204 * Subsystem to access them again and resume it's activity. we are
205 * about to access them externally (fill reportString with actual
206 * data), one can call to this method and suspend subsystem activity.
207 *
208 * @see #SuspendComm
209 *
210 */
211 void ResumeComm();
212
213 /**
214 * Resets communication to CC, to be used when a nonsense command
215 * arrives from CC
216 * @see #ProcessCmd
217 */
218 void ResetConnectionToCC();
219
220
221
222private:
223 /**
224 * C string with CC machine name
225 */
226 char* ccName;
227 /**
228 * Aproximate (+- 500ms) time in microsec, between each report is sent
229 * to CC
230 */
231 unsigned long int reportPeriod;
232
233 unsigned short int portCommandListener;
234 unsigned short int portReportListener;
235
236 //we implement commandListener as a TCPListener derived class, to be
237 //able to custom the behaviour by overriding it's methods, namely
238 //process
239
240 /* maxTimeoutCount. Times subsystem tries to reconnect CC (with reportPeriod)
241 * periodicity, before it considers CC not available.
242 *
243 * After this count is reached Subsystem has to react some way
244 * (parking itself, ...). This is done by
245 * Subsystem::HandleConnectionTimeoutIsOver
246 *
247 * @see #HandleConnectionTimeoutIsOver
248 *
249 */
250
251 short int maxTimeoutCount;
252
253
254 bool locked;
255 bool reporting;
256 pthread_mutex_t mutex4reporting;
257 inline bool Reporting(){
258 pthread_mutex_lock(&mutex4reporting);
259 bool ret=reporting;
260 pthread_mutex_unlock(&mutex4reporting);
261 return ret;
262 }
263 inline void SetReporting(bool trueValue)
264 {
265 pthread_mutex_lock(&mutex4reporting);
266 reporting=trueValue;
267 pthread_mutex_unlock(&mutex4reporting);
268 }
269
270 //we implement reportSender as an instance of class TCPSender
271 TCPSender reportSender;
272 //reporting and trying connections to cc are implemented as
273 //PeriodicActions
274
275 pthread_mutex_t mutex4report;
276 virtual void process();
277 virtual void ClosingChannel();
278
279 bool SendReport();
280 void CheckReportAcknowledge();
281 //to be able to checkreportacknowledge on has to have the timestamp of
282 //the last report sent
283 char lastTimeStamp[TIMESTAMP_LEN];
284 void ExtractTimeStampFromLastReportTo(char *);
285 pthread_t reportThread;
286 inline static void * pthread_ReportingAndCheckingLoop(void* self)
287 {
288 return (void *) ( ((Subsystem* )self)->ReportingAndCheckingLoop() );
289 }
290
291
292 void * ReportingAndCheckingLoop();
293
294 bool acknowledgeReceivedForLastReport;
295 short int timeoutCount;
296 void Lock();
297 void ULock();
298
299};
300
301#endif
Note: See TracBrowser for help on using the repository browser.