The following example assumes that the transmission of the messages takes place over a communications network that charges for the time taken for transmission. It also assumes that there is a cheap-rate period when the unit-time cost is lower. The rules block any transmission of messages until the cheap-rate period. During the cheap-rate period, the queue manager is triggered at regular intervals.
import com.ibm.mqe.*; import java.util.*; /** * Example set of queue manager rules which trigger the transmission * of any messages waiting to be sent. * * These rules only trigger the transmission of messages if the current * time is between the values defined in the variables cheapRatePeriodStart * and cheapRatePeriodEnd * (This example assumes that transmission will take place over a * communication network which charges for the time taken to transmit) */ public class ExampleQueueManagerRules extends MQeQueueManagerRule implements Runnable { // default interval between triggers is 15 seconds private static final long MILLISECS_BETWEEN_TRIGGER_TRANSMITS = 15000; // interval between which we c heck whether the queue manager is closing down. private static final long MILLISECS_BETWEEN_CLOSE_CHECKS = 1000 ; // Max wait of ten seconds to kil off the background thread when // the queue manager is closing down. private static final long MAX_WAIT_FOR_BACKGROUND_THREAD_MILLISECONDS = 10000; // Reference to the control block used to communicate with the background thread // which does a sleep-trigger-sleep-trigger loop. // Note that freeing such blocks for garbage collection will not stop the thread // to which it refers. private Thread th = null; // Flag which is set when shutdown of the background thread is required. // Volatile because the thread using the flag and the thread setting it to true // are different threads, and it is important that the flag is not held in // CPU registers, or one thread will see a different value to the other. private volatile boolean toldToStop = false; //cheap rate transmission period start and end times protected int cheapRatePeriodStart = 18; /*18:00 hrs */ protected int cheapRatePeriodEnd = 9; /*09:00 hrs */ }
The cheapRatePeriodStart and cheapRatePeriodEnd functions define the extent of this cheap rate period. In this example, the cheap-rate period is defined as being between 18:00 hours in the evening until 09:00 hours the following morning.
The constant MILLISECS_BETWEEN_TRIGGER_TRANSMITS defines the period of time, in milliseconds, between each triggering of the queue manager. In this example, the trigger interval is defined to be 15 seconds.
The triggering of the queue manager is handled by a background thread that wakes up at the end of the triggerInterval period. If the current time is inside the cheap rate period, it calls the MQeQueueManager.triggerTransmission() method to initiate an attempt to transmit all messages awaiting transmission. The background thread is created in the queueManagerActivate() rule and stopped in the queueManagerClose() rule. The queue manager calls these rules when it is activated and closed respectively.
/** * Overrides MQeQueueManagerRule.queueManagerActivate() * Starts a timer thread */ public void queueManagerActivate()throws Exception { super.queueManagerActivate(); // background thread which triggers transmission th = new Thread(this, "TriggerThread"); toldToStop = false; th.start(); // start timer thread } /** * Overrides MQeQueueManagerRule.queueManagerClose() * Stops the timer thread */ public void queueManagerClose()throws Exception { super.queueManagerClose(); // Tell the background thread to stop, as the queue manager is closing now. toldToStop = true ; // Now wait for the background thread, if it's not already stopped. if ( th != null) { try { // Only wait for a certain time before giving up and timing out. th.join( MAX_WAIT_FOR_BACKGROUND_THREAD_MILLISECONDS ); // Free up the thread control block for garbage collection. th = null ; } catch (InterruptedException e) { // Don't propogate the exception. // Assume that the thread will stop shortly anyway. } } }
The code to handle the background thread looks like this:
/** * Timer thread * Triggers queue manager every interval until thread is stopped */ public void run() { /* Do a sleep-trigger-sleep-trigger loop until the */ /* queue manager closes or we get an exception.*/ while ( !toldToStop) { try { // Count down until we've waited enough // We do a tight loop with a smaller granularity because // otherwise we would stop a queue manager from closing quickly long timeToWait = MILLISECS_BETWEEN_TRIGGER_TRANSMITS ; while( timeToWait > 0 && !toldToStop ) { // sleep for specified interval Thread.sleep( MILLISECS_BETWEEN_CLOSE_CHECKS ); // We've waited for some time. Account for this in the overall wait. timeToWait -= MILLISECS_BETWEEN_CLOSE_CHECKS ; } if( !toldToStop && timeToTransmit()) { // trigger transmission on QMgr (which is rule owner) ((MQeQueueManager)owner).triggerTransmission(); } } catch ( Exception e ) { e.printStackTrace(); } } } }
The variable owner is defined by the class MQeRule, which is the ancestor of MQeQueueManagerRule. As part of its startup process, the queue manager activates the queue manager rules and passes a reference to itself to the rules object. This reference is stored in the variable owner.
The thread loops indefinitely, as it is stopped by the queueManagerClose() rule, and it sleeps until the end of the MILLISECS_BETWEEN_TRIGGER_TRANSMITS interval period. At the end of this interval, if it has not been told to stop, it calls the timeToTransmit() method to check if the current time is in the cheap-rate transmission period. If this method succeeds, the queue manager's triggerTransmission() rule is called. The timeToTransmit method is shown in the following code:
protected boolean timeToTransmit() { /* get current time */ Calendar calendar = Calendar.getInstance(); calendar.setTime( new Date() ); /* get hour */ int hour = calendar.get( Calendar.HOUR_OF_DAY ); if ( hour >= cheapRatePeriodStart || hour < cheapRatePeriodEnd ) { return true; /* cheap rate */ } else { return false; /* not cheap rate */ } }