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