1 package com.ibm.staf.service.timer;
2
3 /*****************************************************************************/
4 /* Software Testing Automation Framework (STAF) */
5 /* (C) Copyright IBM Corp. 2002, 2005 */
6 /* */
7 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
8 /*****************************************************************************/
9
10 /****************************************************************************/
11 //
12 // Class: TimerObject
13 //
14 // Logical Name: TimerObject.java
15 //
16 // Description: This class represents the actual timers.
17 //
18 //
19 // History:
20 //
21 // DATE DEVELOPER CHANGE DESCRIPTION
22 // ---------- ----------- -----------------------------------
23 // 02/01/2000 C Alkov Original Program
24 //
25 /****************************************************************************/
26
27 import java.util.Date;
28 import com.ibm.staf.*;
29 import com.ibm.staf.wrapper.STAFLog;
30 import java.io.Serializable;
31 import java.io.ObjectInputStream;
32 import java.util.Map;
33 import java.util.HashMap;
34
35 public class TimerObject implements Runnable, Serializable
36 {
37 private String name;
38 private String timerString;
39 private long frequency;
40 private long priority;
41 private String machine;
42 private int handle;
43 private String handleName;
44 private String key;
45 private Date lastFireTime;
46 private Date nextFireTime;
47 private boolean unregisterOnNoPath;
48 private boolean unregisterOnNoHandle;
49 private boolean noPathVarSet;
50 private boolean noHandleVarSet;
51 private boolean byname;
52 private int failCount;
53
54 /* Do not serialize (transient) this instance variable since
55 reference will be different from run to run */
56 private transient TimerRequestHandler reqHandler;
57
58 /****************************************************************************/
59 //
60 // Method:
61 // Constructor
62 //
63 // Description:
64 // Constructor method for TimerObject class.
65 //
66 // Input:
67 // fName - The String Name (Type) of this timer.
68 // fMachine - The machine name (endpoint) this timer should notify.
69 // fHandle - The Handle # of the process on the machine this
70 // timer should notify.
71 // fHandleName - The handle name of the process this timer should notify.
72 // fKey - The key of this timer (or "" if none was specified)
73 // fFrequency - The frequency of this timer.
74 // fPriority - The priority of the Queue message this timer should
75 // send to the registered machine.
76 // rHandler - The requestHandlerObject which created this Timer.
77 // fUnregOnNoPath - int representing the timer specific variable for
78 // UnregisterOnNoPath
79 // fUnregOnNoHandle - int representing the timer specific variable for
80 // UnregisterOnNoHandle
81 // fByname - Boolean that specifies if the BYNAME parameter was specified.
82 //
83 // Exceptions Thrown:
84 // none
85 //
86 // Notes:
87 // none
88 //
89 /****************************************************************************/
90
TimerObject(String fName, String fMachine, int fHandle, String fHandleName, String fKey, long fFrequency, long fPriority, TimerRequestHandler rHandler, int fUnregOnNoPath, int fUnregOnNoHandle, boolean fByname)91 public TimerObject(String fName, String fMachine, int fHandle,
92 String fHandleName, String fKey,
93 long fFrequency, long fPriority,
94 TimerRequestHandler rHandler, int fUnregOnNoPath,
95 int fUnregOnNoHandle, boolean fByname)
96 {
97 name = fName;
98 machine = fMachine;
99 handle = fHandle;
100 handleName = fHandleName;
101 key = fKey;
102 frequency = fFrequency;
103 priority = fPriority;
104 lastFireTime = null;
105 reqHandler = rHandler;
106 noHandleVarSet = false;
107 noPathVarSet = false;
108 byname = fByname;
109 failCount = 0;
110
111 /* Set timer specific values for unregister on no path/handle */
112
113 if (fUnregOnNoPath == 1)
114 {
115 unregisterOnNoPath = true;
116 noPathVarSet = true;
117 }
118 else if (fUnregOnNoPath == 0)
119 {
120 unregisterOnNoPath = false;
121 noPathVarSet = true;
122 }
123
124 if (fUnregOnNoHandle == 1)
125 {
126 unregisterOnNoHandle = true;
127 noHandleVarSet = true;
128 }
129 else if(fUnregOnNoHandle == 0)
130 {
131 unregisterOnNoHandle = false;
132 noHandleVarSet = true;
133 }
134
135 /* create timer string for key */
136
137 if (byname)
138 {
139 timerString = TimerUtils.createTimerString(
140 name, machine, handleName, key);
141 }
142 else
143 {
144 timerString = TimerUtils.createTimerString(
145 name, machine, handle, key);
146 }
147
148 /* find first fire time */
149
150 nextFireTime = this.findNextFireTime();
151
152 /* add to timer list */
153
154 reqHandler.timerList.put(timerString, this);
155 reqHandler.tManager.wakeUpManager();
156 }
157
getMachine()158 public String getMachine()
159 {
160 return machine;
161 }
162
163 /****************************************************************************/
164 //
165 // Method:
166 // findNextFireTime
167 //
168 // Description:
169 // Calculates the next time this timer should fire a message.
170 //
171 // Input:
172 // none
173 //
174 // Exceptions Thrown:
175 // none
176 //
177 // Notes:
178 // none
179 //
180 /****************************************************************************/
181
findNextFireTime()182 private Date findNextFireTime()
183 {
184 Date currentDate = new Date();
185 long fireTime = currentDate.getTime() + frequency;
186 return new Date(fireTime);
187
188 }
189
190 /****************************************************************************/
191 //
192 // Method:
193 // fire
194 //
195 // Description:
196 // This method starts a thread which will fire the message
197 // to the process on the machine which was registered for
198 // this timer.
199 //
200 // Input:
201 // none
202 //
203 // Exceptions Thrown:
204 // none
205 //
206 // Notes:
207 // synchronized method
208 //
209 /****************************************************************************/
210
fire()211 public synchronized void fire()
212 {
213 /* Store this fire time and calculate next fire time */
214
215 Date currentTime = new Date();
216 lastFireTime = currentTime;
217 nextFireTime = new Date(currentTime.getTime() + frequency);
218
219 /* Start thread to send message, using STAF QUEUE service */
220
221 Thread thisThread = new Thread(this, timerString);
222 thisThread.start();
223
224 }
225
226 /****************************************************************************/
227 //
228 // Method:
229 // getNextFireTime
230 //
231 // Description:
232 // Returns the nextFireTime for this timer.
233 //
234 // Input:
235 // none
236 //
237 // Exceptions Thrown:
238 // none
239 //
240 // Notes:
241 // synchronized method
242 //
243 /****************************************************************************/
244
getNextFireTime()245 public synchronized Date getNextFireTime()
246 {
247 return this.nextFireTime;
248
249 }
250
251 /****************************************************************************/
252 //
253 // Method:
254 // getProperties
255 //
256 // Description:
257 // Returns the properties of this timer in a marshalled map for use in the
258 // LIST TIMERS request.
259 //
260 // Input:
261 // longFormat - boolean set to true if LONG is specified in the LIST request
262 // so that more detailed information on each timer is provided
263 //
264 // Exceptions Thrown:
265 // none
266 //
267 // Notes:
268 // synchronized method
269 //
270 /****************************************************************************/
271
getProperties(boolean longFormat)272 public synchronized Map getProperties(boolean longFormat)
273 {
274 Map properties;
275
276 if (longFormat)
277 properties = reqHandler.fTimerLongMapClass.createInstance();
278 else
279 properties = reqHandler.fTimerMapClass.createInstance();
280
281 properties.put("type", name);
282 properties.put("frequency", String.valueOf(frequency));
283 properties.put("machine", machine);
284
285 if (byname)
286 {
287 properties.put("notifyBy", "Name");
288 properties.put("notifiee", handleName);
289 }
290 else
291 {
292 properties.put("notifyBy", "Handle");
293 properties.put("notifiee", String.valueOf(handle));
294 }
295
296 properties.put("key", key);
297
298 if (lastFireTime != null)
299 properties.put("lastTimestamp", TimerUtils.formatTime(lastFireTime));
300
301 if (longFormat)
302 {
303 properties.put("priority", String.valueOf(priority));
304
305 if (noPathVarSet)
306 properties.put("unRegOnNoPath",
307 String.valueOf(unregisterOnNoPath));
308 else
309 properties.put("unRegOnNoPath", "global");
310
311 if (noHandleVarSet)
312 properties.put("unRegOnNoHandle",
313 String.valueOf(unregisterOnNoHandle));
314 else
315 properties.put("unRegOnNoHandle", "global");
316 }
317
318 return properties;
319 }
320
321 /****************************************************************************/
322 //
323 // Method:
324 // run
325 //
326 // Description:
327 // The run method of the TimerObject class. Causes the timer
328 // to send a message to the process on the machine which
329 // registered the timer.
330 //
331 // Input:
332 // none
333 //
334 // Exceptions Thrown:
335 // none
336 //
337 // Notes:
338 // synchronized method
339 //
340 /****************************************************************************/
341
run()342 public synchronized void run()
343 {
344 String where = machine;
345 String service = "QUEUE";
346 Date currentTime = new Date();
347 String formattedTime = TimerUtils.formatTime(currentTime);
348 String queueType = "STAF/Service/Timer";
349
350 // Create a marshalled map containing the message
351
352 Map messageMap = new HashMap();
353 messageMap.put("timerServiceName", reqHandler.sName);
354 messageMap.put("type", name);
355 messageMap.put("timestamp", formattedTime);
356 messageMap.put("key", key);
357
358 STAFMarshallingContext mc = new STAFMarshallingContext();
359 mc.setRootObject(messageMap);
360 String message = mc.marshall();
361
362 String request;
363
364 if (byname)
365 {
366 request = "QUEUE NAME " + handleName + " PRIORITY " + priority +
367 " TYPE " + STAFUtil.wrapData(queueType) +
368 " MESSAGE " + STAFUtil.wrapData(message);
369 }
370 else
371 {
372 request = "QUEUE HANDLE " + handle + " PRIORITY " + priority +
373 " TYPE " + STAFUtil.wrapData(queueType) +
374 " MESSAGE " + STAFUtil.wrapData(message);
375 }
376
377 try
378 {
379 String result = reqHandler.sHandle.submit(where, service, request);
380
381 // If this timer is registered byname, see if any processes were
382 // available to receive messages on target machine. If not, handle
383 // as if HandleDoesNotExist.
384
385 if (byname)
386 {
387 if (Integer.parseInt(result) == 0)
388 {
389 // No processes registered to this handle name
390 // See if we should unregister
391
392 if (!this.noHandleVarSet)
393 {
394 // Use global variable
395
396 if (reqHandler.unregisterOnNoHandle)
397 {
398 // unregister and log
399 reqHandler.timer.log.log(
400 STAFLog.Info, "No processes registered to " +
401 "handle name " + handleName +
402 ", unregistering timer: " + this.timerString);
403 reqHandler.unregister(timerString);
404 return;
405 }
406 }
407 else if (this.unregisterOnNoHandle)
408 {
409 // Use timer specified variable
410 // Unregister and log
411
412 reqHandler.timer.log.log(
413 STAFLog.Info, "No processes registered to " +
414 "handle name " + handleName +
415 ", unregistering timer: " + this.timerString);
416 reqHandler.unregister(timerString);
417 return;
418 }
419
420 // Did not unregister the timer, log error and continue
421
422 reqHandler.timer.log.log(
423 STAFLog.Warning, "No processes registered to handle " +
424 "name " + handleName + " for timer: " + this.timerString);
425
426 return;
427 }
428 }
429 }
430 catch (STAFException e)
431 {
432 // STAF threw exception, see what problem was and handle appropriately
433
434 if(e.rc == STAFResult.HandleDoesNotExist)
435 {
436 // Handle does not exist. See if we should unregister timer.
437
438 if (!this.noHandleVarSet)
439 {
440 // Use global variable
441
442 if (reqHandler.unregisterOnNoHandle)
443 {
444 // Unregister and log
445
446 reqHandler.timer.log.log(
447 STAFLog.Info, "Registered handle does not exist, " +
448 "unregistering timer: " + this.timerString);
449 reqHandler.unregister(timerString);
450 return;
451 }
452 }
453 else if (this.unregisterOnNoHandle)
454 {
455 // Use timer specific variable
456 // Unregister and log
457
458 reqHandler.timer.log.log(
459 STAFLog.Info, "Registered handle does not exist, " +
460 "unregistering timer: " + this.timerString);
461 reqHandler.unregister(timerString);
462 return;
463 }
464
465 // Did not unregister the timer, log error and continue
466
467 reqHandler.timer.log.log(
468 STAFLog.Warning, "Registered handle does not exist for " +
469 "timer: " + this.timerString);
470
471 return;
472 }
473 else if (e.rc == STAFResult.NoPathToMachine ||
474 e.rc == STAFResult.CommunicationError)
475 {
476 // No path to machine. See if we should unregister timer.
477
478 if (!this.noPathVarSet)
479 {
480 // Use global variable
481
482 if(reqHandler.unregisterOnNoPath)
483 {
484 failCount++; // increment failCount
485
486 if (failCount >= reqHandler.failCountLimit)
487 {
488 // Unregister and log
489
490 reqHandler.timer.log.log(
491 STAFLog.Info,
492 "Not able to contact registered machine, "+
493 "unregistering timer: "+this.timerString);
494 reqHandler.unregister(timerString);
495 return;
496 }
497 else
498 {
499 // Do not unregister, just log
500
501 reqHandler.timer.log.log(
502 STAFLog.Info,
503 "Not able to contact registered machine, "+
504 "for timer: "+this.timerString+" This is attempt:"
505 +failCount);
506 return;
507 }
508 }
509 }
510 else if (this.unregisterOnNoPath)
511 {
512 // Use timer specific variable
513
514 failCount++; // increment failCount
515
516 if (failCount >= reqHandler.failCountLimit)
517 {
518 // Unregister and log
519
520 reqHandler.timer.log.log(
521 STAFLog.Info,
522 "Not able to contact registered machine, "+
523 "unregistering timer: "+this.timerString);
524 reqHandler.unregister(timerString);
525 return;
526 }
527 else
528 {
529 // Do not unregister, just log
530
531 reqHandler.timer.log.log(
532 STAFLog.Info,
533 "Not able to contact registered machine, "+
534 "for timer: "+this.timerString+" This is attempt:"+
535 failCount);
536 return;
537 }
538 }
539
540 // Did not unregister the timer, log error and continue
541
542 reqHandler.timer.log.log(
543 STAFLog.Warning,
544 "Not able to contact registered machine, "+
545 "for timer: "+this.timerString);
546 }
547 else
548 {
549 /* Log error */
550 reqHandler.timer.log.log(
551 STAFLog.Info,
552 "Unexpected error sending message "+
553 "for timer: "+this.timerString+" RC="+e.rc);
554 }
555 }
556 }
557
558 /****************************************************************************/
559 //
560 // Method:
561 // setReqHandler
562 //
563 // Description:
564 // Sets the RequestHandler for the TimerObject.
565 //
566 // Input:
567 // aReqHandler - Reference to the current RequestHandler
568 //
569 // Exceptions Thrown:
570 // none
571 //
572 // Notes:
573 // none
574 //
575 /****************************************************************************/
576
setReqHandler(TimerRequestHandler aReqHandler)577 public void setReqHandler(TimerRequestHandler aReqHandler)
578 {
579 reqHandler = aReqHandler;
580 }
581
582 /****************************************************************************/
583 //
584 // Method:
585 // update
586 //
587 // Description:
588 // Updates the frequency and priority of the Timer.
589 //
590 // Input:
591 // newFrequency - The new frequency of the timer.
592 // newPriority - The new priority of the timer.
593 // fUnregOnNoPath - specifies a timer specific variable for unregisterOnNoPath
594 // a value of -1 means use the global variable (not timer specific)
595 // fUnregOnNoHandle - specifies a timer specific variable for unregisterOnNoHandle
596 // a value of -1 means use the global variable (not timer specific)
597 //
598 // Exceptions Thrown:
599 // none
600 //
601 // Notes:
602 // synchronized method
603 //
604 /****************************************************************************/
605
update(long newFrequency, long newPriority, int fUnregOnNoPath, int fUnregOnNoHandle)606 public synchronized void update(long newFrequency, long newPriority,
607 int fUnregOnNoPath, int fUnregOnNoHandle)
608 {
609 frequency = newFrequency;
610 priority = newPriority;
611 noHandleVarSet = false;
612 noPathVarSet = false;
613
614 // Set timer specific values for unregister on no path/handle.
615 // A value of -1 means to use global value for variable.
616
617 if (fUnregOnNoPath == 1)
618 {
619 unregisterOnNoPath = true;
620 noPathVarSet = true;
621 }
622 else if (fUnregOnNoPath == 0)
623 {
624 unregisterOnNoPath = false;
625 noPathVarSet = true;
626 }
627
628 if (fUnregOnNoHandle == 1)
629 {
630 unregisterOnNoHandle = true;
631 noHandleVarSet = true;
632 }
633 else if(fUnregOnNoHandle == 0)
634 {
635 unregisterOnNoHandle = false;
636 noHandleVarSet = true;
637 }
638
639 // Update nextFireTime
640
641 if (lastFireTime == null)
642 {
643 nextFireTime = findNextFireTime();
644 }
645 else
646 {
647 nextFireTime = new Date(lastFireTime.getTime() + frequency);
648 }
649 }
650
651 }
652