docs: public final void alarm(Object obj)
      {
          if (messagingEngine != null) SibTr.push(messagingEngine);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "alarm", "Expiry=" + expiryIndex.size());
          
          synchronized (lockObject)
          {
              // we try ensure there is only ever 1 alarm thread running and check at the end of each alarm 
              // if another needs scheduling.  3 consecutive checked exceptions are tolerated.
              alarmScheduled = false;
              
              while (alarming)
              {
                  // this is only now possible with a highly unlikely thread scheduling, but cope with it
                  // anyway.
                  try
                  {
                      lockObject.wait();
                  }
                  catch (InterruptedException e)
                  {
                      // No FFDC Code Needed
                  }
              }
              
              alarming = true;
          }
  
          LocalTransaction transaction = null;
          int indexUsed = 0;
          long processed = 0;
          long expired = 0;
          long cleaned = 0;
          long gone = 0;
          long remain = 0;
  
          try
          {
              // Once every 5 cycles, set the flag to initiate full-index scan
              // for items which are no longer in the store.
              countForCleanup++;
              if (countForCleanup >= cleanupLimit)
              {
                  countForCleanup = 0;
                  cleanupDeletedItems = true;
              }
              else
              {
                  cleanupDeletedItems = false;
              }
  
              // Get current system time for start of cycle
              startTime = System.currentTimeMillis();
              indexUsed = saveStartTime(startTime);
  
              // Point to the start of the tree                  
              expiryIndex.resetIterator();
  
              // Get the first entry from the index and start the cycle
              ExpirableReference expirableRef = expiryIndex.next();
              while (runEnabled && expirableRef != null && expirableRef.getExpiryTime() <= startTime)
              {
                  processed++;
  
                  Expirable expirable = (Expirable) expirableRef.get();
                  // If the weak reference is null or if the item indicates that it has
                  // already gone from the store, then remove the expirable ref from the index 
                  if (expirable != null && expirable.expirableIsInStore())
                  {
                      // Now processing items which are either at or past their expiry time.
                      // Create a transaction if we don't have one already
                      if (transaction == null)
                      {
                          transaction = messageStore.getTransactionFactory().createLocalTransaction();
                      }
                      // Tell the expirable to expire. If it returns true, then remove it from the expiry index.
                      if (expirable.expirableExpire((PersistentTransaction)transaction))
                      {
                          expired++;
                          // Remove from expiry index
                          remove(expirableRef, true);
                          batchCount++;
                          if (batchCount >= BATCH_SIZE)
                          {
                              transaction.commit();
                              transaction = null;
                              batchCount = 0;
                          }
                      }
                      else
                      {
                          remain++;
                      }
                  }
                  else
                  {
                      if (remove(expirableRef, false))
                      {
                          gone++;
                      }
                  }
                  expirableRef = expiryIndex.next();
              }
  
              // Once every 'n' cycles, continue to the end of the expiry index
              // removing any entries for items which are no longer in the store.
              if (cleanupDeletedItems)
              {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Expiry cleanup in progress");
  
                  while (runEnabled && expirableRef != null)
                  {
                      Expirable expirable = (Expirable) expirableRef.get();
                      // If the weak reference is null or if the item indicates that it has
                      // gone from the store, then remove the expirable ref from the index 
                      if (expirable == null || !(expirable.expirableIsInStore()))
                      {
                          if (remove(expirableRef, false))
                          {
                              cleaned++;
                          }
                      }
                      expirableRef = expiryIndex.next();
                  }
                  // Check how much useful work we did, and vary the frequency 
                  // of the cleanup cycle. 199808.1 
                  if (cleaned < 10 && cleanupLimit < 100)
                  {
                      cleanupLimit += CLEANUP_EVERY_N_CYCLES; // Slow down
                  }
                  else if (cleaned > 1000 && cleanupLimit > CLEANUP_EVERY_N_CYCLES)
                  {
                      cleanupLimit = CLEANUP_EVERY_N_CYCLES; // Restore default
                  }
                  else if (cleaned > 100 && cleanupLimit > CLEANUP_EVERY_N_CYCLES)
                  {
                      cleanupLimit -= CLEANUP_EVERY_N_CYCLES; // Speed up
                  }
              }
  
              if (transaction != null) // Did we create a transaction?
              {
                  if (batchCount == 0) // No work outstanding  
                  {
                      transaction.rollback();
                  }
                  else // Work outstanding, must be committed  
                  {
                      transaction.commit();
                      batchCount = 0;
                  }
                  transaction = null;
              }
              consecutiveFailures = 0;
          } // end try
          catch (Exception e)
          {
              com.ibm.ws.ffdc.FFDCFilter.processException(e, "com.ibm.ws.sib.msgstore.expiry.Expirer.run", "441", this);
              if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "alarm", "Expiry thread exception: " + e);
  
              consecutiveFailures++;
              lastException = e;
              lastExceptionTime = timeNow();
              
              if (consecutiveFailures > MAX_CONSECUTIVE_FAILURES)
              {
                  synchronized (lockObject)
                  {
                      runEnabled = false;
                      addEnabled = false;    
                  }
                  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "alarm", e);
                  throw new MessageStoreRuntimeException("EXPIRY_DAEMON_TERMINATED_SIMS2001", new Object[] { e}, e);
              }
          } 
          finally
          {
              long currIndexSize = 0;
              // Synchronize while we decide whether to schedule another alarm or not
              synchronized (lockObject)
              {
                  alarming = false;
                  currIndexSize = expiryIndex.size();
                  
                  if (runEnabled) // We have not been told to stop,
                  {
                      if (currIndexSize > 0) // and the index is not empty, 
                      {
                          scheduleAlarm(interval); // ... schedule the next alarm
                      }
                  }
                  else // Expirer is stopping
                  {
                      // Disallow addition of any further expirables to the index.
                      addEnabled = false;
                  }
                  lockObject.notifyAll();
              }
  
          
  
              // Save statistics for diagnostic dump using the same log index as
              // returned by saveStartTime() called at start of this cycle.
              logIndexSize[indexUsed] = currIndexSize;
              logProcessed[indexUsed] = processed;
              logExpired[indexUsed] = expired;
              logGone[indexUsed] = gone;
              logRemain[indexUsed] = remain;
              logCleaned[indexUsed] = cleaned;
  
          }
          
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "alarm", " processed="+processed+" gone="+ gone+ " expired="+ expired+ " remain="+ remain+ " cleaned="+ cleaned+ " expiry="+ expiryIndex.size()+ " cl="+ cleanupLimit+ " alarmScheduled="+ alarmScheduled);
  
          if (messagingEngine != null) SibTr.pop();
      }