Determine, whether another one of *our* devices is stale or not.

@param userDevice our omemoDevice
@param subject another one of our devices
@param lastReceipt date of last received message from that device
@param maxAgeHours threshold

@return staleness
12892
static boolean isStale(OmemoDevice userDevice, OmemoDevice subject, Date lastReceipt, int maxAgeHours) {
        if (userDevice.equals(subject)) {
            return false;
        }

        if (lastReceipt == null) {
            return false;
        }

        long maxAgeMillis = MILLIS_PER_HOUR * maxAgeHours;
        Date now = new Date();

        return now.getTime() - lastReceipt.getTime() > maxAgeMillis;
    }
250377
@Override
   public boolean isExpired(long address) {
      // 16 bytes for eviction if needed (optional)
      // 8 bytes for linked pointer
      int offset = evictionEnabled ? 24 : 8;

      byte metadataType = MEMORY.getByte(address, offset);
      if ((metadataType & IMMORTAL) != 0) {
         return false;
      }
      // type
      offset += 1;
      // hashCode
      offset += 4;
      // key length
      int keyLength = MEMORY.getInt(address, offset);
      offset += 4;

      long now = timeService.wallClockTime();

      byte[] metadataBytes;
      if ((metadataType & CUSTOM) == CUSTOM) {
         // TODO: this needs to be fixed in ISPN-8539
         return false;
//         int metadataLength = MEMORY.getInt(address, offset);
//         metadataBytes = new byte[metadataLength];
//
//         // value and keyLength
//         offset += 4 + keyLength;
//
//         MEMORY.getBytes(address, offset, metadataBytes, 0, metadataBytes.length);
//
//         Metadata metadata;
//         try {
//            metadata = (Metadata) marshaller.objectFromByteBuffer(metadataBytes);
//            // TODO: custom metadata is not implemented properly for expiration
//            return false;
//         } catch (IOException | ClassNotFoundException e) {
//            throw new CacheException(e);
//         }
      } else {
         // value and keyLength
         offset += 4 + keyLength;

         // If it has version that means we wrote the size as well which goes after key length
         if ((metadataType & HAS_VERSION) != 0) {
            offset += 4;
         }

         switch (metadataType & 0xFC) {
            case MORTAL:
               metadataBytes = new byte[16];
               MEMORY.getBytes(address, offset, metadataBytes, 0, metadataBytes.length);
               return ExpiryHelper.isExpiredMortal(Bits.getLong(metadataBytes, 0), Bits.getLong(metadataBytes, 8), now);
            case TRANSIENT:
               metadataBytes = new byte[16];
               MEMORY.getBytes(address, offset, metadataBytes, 0, metadataBytes.length);
               return ExpiryHelper.isExpiredTransient(Bits.getLong(metadataBytes, 0), Bits.getLong(metadataBytes, 8), now);
            case TRANSIENT_MORTAL:
               metadataBytes = new byte[32];
               MEMORY.getBytes(address, offset, metadataBytes, 0, metadataBytes.length);
               long lifespan = Bits.getLong(metadataBytes, 0);
               long maxIdle = Bits.getLong(metadataBytes, 8);
               long created = Bits.getLong(metadataBytes, 16);
               long lastUsed = Bits.getLong(metadataBytes, 24);
               return ExpiryHelper.isExpiredTransientMortal(maxIdle, lastUsed, lifespan, created, now);
            default:
               return false;
         }
      }
   }
650892
@Override
  public void onEvictionFromHeap(final Entry<K, V> e) {
    CacheEntry<K,V> _currentEntry = heapCache.returnCacheEntry(e);
    if (syncEntryEvictedListeners != null) {
      for (CacheEntryEvictedListener<K, V> l : syncEntryEvictedListeners) {
        l.onEntryEvicted(this, _currentEntry);
      }
    }
  }
1318812
public boolean expire(boolean cancelTimer)
  {
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.entry(tc, "expire", new Boolean(cancelTimer));

    if ((expiryHandle != null) && cancelTimer)
    {
      expiryHandle.cancel();
    }
    expiryHandle = null;
    if (!satisfied)
    {
      expired = true;
      if (TraceComponent.isAnyTracingEnabled() && UserTrace.tc_mt.isDebugEnabled())    
        SibTr.debug(UserTrace.tc_mt,       
           nls_mt.getFormattedMessage(
           "REMOTE_REQUEST_EXPIRED_CWSJU0033",
           new Object[] {
             tick},
           null));
    }

    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.exit(tc, "expire", new Boolean(expired));

    return expired;
  }
773987
@Override
    public void registerStoppableAsynchConsumerCallback(
                                                        StoppableAsynchConsumerCallback callback,
                                                        int maxActiveMessages,
                                                        long messageLockExpiry,
                                                        int maxBatchSize,
                                                        Reliability unrecoverableReliability,
                                                        boolean inLine,
                                                        OrderingContext extendedMessageOrderingContext,
                                                        int maxSequentialFailures,
                                                        long hiddenMessageDelay)
                    throws SISessionUnavailableException, SISessionDroppedException, SIIncorrectCallException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(tc, "registerStoppableAsynchConsumerCallback",
                        new Object[] { callback,
                                      maxActiveMessages,
                                      messageLockExpiry,
                                      maxBatchSize,
                                      unrecoverableReliability,
                                      inLine,
                                      extendedMessageOrderingContext,
                                      maxSequentialFailures,
                                      hiddenMessageDelay });

        //register the AsynchConsumer with the LCP
        _localConsumerPoint.registerStoppableAsynchConsumer(
                                                            callback,
                                                            maxActiveMessages,
                                                            messageLockExpiry,
                                                            maxBatchSize,
                                                            unrecoverableReliability,
                                                            inLine,
                                                            (OrderingContextImpl) extendedMessageOrderingContext,
                                                            null, // No callback busy lock is used for non-mediation consumers.
                                                            maxSequentialFailures,
                                                            hiddenMessageDelay);

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "registerStoppableAsynchConsumerCallback");
    }
442305
private static boolean meetsThresholdRequirement(long timeTaken) {
        final P6LogLoadableOptions opts = P6LogOptions.getActiveInstance();
        long executionThreshold = null != opts ? opts.getExecutionThreshold() : 0;
    
    return executionThreshold <= 0 || TimeUnit.NANOSECONDS.toMillis(timeTaken) > executionThreshold;
  }
241645
public void setAsynchConsumer(AsynchConsumerCallback consumer,
                                 int maxActiveMessages,
                                 long messageLockExpiry,
                                 int maxBatchSize,
                                 OrderingContext orderContext,
                                 int maxSequentialFailures,                                             //SIB0115d.comms
                                 long hiddenMessageDelay,
                                 boolean stoppable)                                                             //472879
      throws SISessionUnavailableException, SISessionDroppedException,
             SIConnectionUnavailableException, SIConnectionDroppedException,
             SIErrorException,
             SIIncorrectCallException
   {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "setAsynchConsumer",
                                           new Object[]
                                           {
                                              consumer,
                                              maxActiveMessages,
                                              messageLockExpiry,
                                              maxBatchSize,
                                              orderContext,
                                              maxSequentialFailures,                                    //SIB0115d.comms
                                              hiddenMessageDelay,
                                              stoppable                                                         //472879
                                           });

      if (sessionId == 0)
      {
         // If the session Id = 0, then no one called setSessionId(). As such we are unable to flow
         // to the server as we do not know which session to instruct the server to use.
         SIErrorException e = new SIErrorException(
            nls.getFormattedMessage("SESSION_ID_HAS_NOT_BEEN_SET_SICO1043", null, null)
         );

         FFDCFilter.processException(e, CLASS_NAME + ".setAsyncConsumer",
                                     CommsConstants.CONVERSATIONHELPERIMPL_02, this);

         if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Session Id was 0", e);

         throw e;
      }

      CommsByteBuffer request = getCommsByteBuffer();
      // Connection object id
      request.putShort(connectionObjectId);
      // Consumer session id
      request.putShort(sessionId);
      // Now put the message order context id if we have one
      if (orderContext != null)
      {
         request.putShort(((OrderingContextProxy)orderContext).getId());
      }
      else
      {
         request.putShort(CommsConstants.NO_ORDER_CONTEXT);
      }
      // Client session id - this is the proxy queue ID
      request.putShort(proxyQueueId);
      // Max active messages
      request.putInt(maxActiveMessages);
      // Message lock expiry
      request.putLong(messageLockExpiry);
      // Max batch size
      request.putInt(maxBatchSize);

      // If callback is Stoppable then send maxSequentialFailures & hiddenMessageDelay then change the
      // Segment Id to Stoppable  SIB0115d.comms
      int JFapSegmentId = JFapChannelConstants.SEG_REGISTER_ASYNC_CONSUMER;                             //SIB0115d.comms

      if (stoppable) {                                                                           //SIB0115d.comms,472879
        request.putInt(maxSequentialFailures);                                                          //SIB0115d.comms
        request.putLong(hiddenMessageDelay);
        JFapSegmentId = JFapChannelConstants.SEG_REGISTER_STOPPABLE_ASYNC_CONSUMER;                     //SIB0115d.comms
      }                                                                                                 //SIB0115d.comms

      CommsByteBuffer reply = null;
      try
      {
         // Pass on call to server
         reply = jfapExchange(request,
                              JFapSegmentId,                                                            //SIB0115d.comms
                              JFapChannelConstants.PRIORITY_MEDIUM,
                              true);
      }
      catch (SIConnectionLostException e)
      {
         // No FFDC Code needed
         // Converting this to a connection dropped as that is all we can throw
         if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Connection was lost", e);

         throw new SIConnectionDroppedException(e.getMessage(), e);
      }

      // Confirm appropriate data returned
      try
      {
         short err = reply.getCommandCompletionCode(JFapChannelConstants.SEG_REGISTER_ASYNC_CONSUMER_R);
         if (err != CommsConstants.SI_NO_EXCEPTION)
         {
            checkFor_SISessionUnavailableException(reply, err);
            checkFor_SISessionDroppedException(reply, err);
            checkFor_SIConnectionUnavailableException(reply, err);
            checkFor_SIConnectionDroppedException(reply, err);
            checkFor_SIIncorrectCallException(reply, err);
            checkFor_SIErrorException(reply, err);
            defaultChecker(reply, err);
         }
      }
      finally
      {
         if (reply != null) reply.release();
      }

      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "setAsynchConsumer");
   }
893524
protected void intialiseNonPersistent(MultiMEProxyHandler proxyHandler,
                                        Neighbours neighbours)
  {
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.entry(tc, "intialiseNonPersistent");

    iProxyHandler = proxyHandler;
    iNeighbours = neighbours;
    iDestinationManager =
      iProxyHandler.getMessageProcessor().getDestinationManager();
    iRemoteQueue = SIMPUtils.createJsSystemDestinationAddress(
          SIMPConstants.PROXY_SYSTEM_DESTINATION_PREFIX, iMEUuid, iBusId);
    if (iMEUuid == null)
      iMEUuid = iRemoteQueue.getME();

    iProxies = new Hashtable();

    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.exit(tc, "intialiseNonPersistent");
  }
837555
public boolean checkRepeatMove ()
    {
        long now = System.currentTimeMillis();
        if (now - _lastRequestTime < STALE_REQUEST_DURATION) {
            return true;

        } else {
            _lastRequestTime = now;
            return false;
        }
    }
893907
public synchronized void checkNotExpired() {
        if (Utils.currentTimeSeconds() > getExpiryTime()) {
            stateMachine.transition(State.EXPIRED);
            disconnectFromChannel();
            throw new IllegalStateException("Channel expired");
        }
    }
534366
public void setThreadKeepAliveTime(int threadKeepAliveTime) {
        this.threadKeepAliveTime = Math.max(MIN_RECEIVE_THREAD_KEEP_ALIVE_TIME, threadKeepAliveTime);
        executor.setKeepAliveTime(threadKeepAliveTime, TimeUnit.SECONDS);
    }
1193237
public final void checkTemporaryDestinationScope( Destination destination ) throws JMSException
    {
    	if (destination instanceof LocalQueue)
    	{
    		LocalQueue localQueue = (LocalQueue)destination; 
	        if (localQueue.isTemporary() && !connection.isRegisteredTemporaryQueue(localQueue.getQueueName()))
	       		throw new IllegalStateException("Temporary queue does not belong to session's connection.");
    	}
    	else
    	if (destination instanceof LocalTopic)
    	{	
    		LocalTopic localTopic = (LocalTopic)destination; 
	        if (localTopic.isTemporary() && !connection.isRegisteredTemporaryTopic(localTopic.getTopicName()))
	       		throw new IllegalStateException("Temporary topic does not belong to session's connection.");
    	}
    	else
    		throw new FFMQException("Unexpected destination type : "+destination,"INTERNAL_ERROR");
    }
408476
@Override
    public void setDeliveryDelay(long deliveryDelayTime) throws JMSException {

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(this, tc, "setDeliveryDelay", deliveryDelayTime);

        checkClosed();
        // Throws an exception if this is not a valid time to live.
        validateDeliveryDelayTime(deliveryDelayTime);
        // We know by this point that it must be valid.
        this.defaultDeliveryDelay = deliveryDelayTime;

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(this, tc, "setDeliveryDelay");

    }
557445
public void processResetRequestAck(long dmeVersion, SendDispatcher sendDispatcher)
  {
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.entry(tc, "processResetRequestAck", Long.valueOf(dmeVersion));

    // Only consider non-stale request acks
    if (dmeVersion >= _latestDMEVersion)
    {
      if (dmeVersion > _latestDMEVersion)
        _latestDMEVersion = dmeVersion;

      _slowedGetTOM.applyToEachEntry(new AddToEagerTOM(_slowedGetTOM, dmeVersion));
      sendDispatcher.sendResetRequestAckAck(dmeVersion);
    }

    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
      SibTr.exit(tc, "processResetRequestAck");
  }
269155
CompletableFuture<Boolean> actualRemoveMaxIdleExpireEntry(K key, V value, long maxIdle, boolean skipLocking) {
      CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
      Object expiringObject = expiring.putIfAbsent(key, completableFuture);
      if (expiringObject == null) {
         if (trace) {
            log.tracef("Submitting expiration removal for key %s which had maxIdle of %s", toStr(key), maxIdle);
         }
         completableFuture.whenComplete((b, t) -> expiring.remove(key, completableFuture));
         try {
            AdvancedCache<K, V> cacheToUse = skipLocking ? cache.withFlags(Flag.SKIP_LOCKING) : cache;
            CompletableFuture<Boolean> expired = cacheToUse.removeMaxIdleExpired(key, value);
            expired.whenComplete((b, t) -> {
               if (t != null) {
                  completableFuture.completeExceptionally(t);
               } else {
                  completableFuture.complete(b);
               }
            });
            return completableFuture;
         } catch (Throwable t) {
            completableFuture.completeExceptionally(t);
            throw t;
         }
      } else if (expiringObject instanceof CompletableFuture) {
         // This means there was another thread that found it had expired via max idle
         return (CompletableFuture<Boolean>) expiringObject;
      } else {
         // If it wasn't a CompletableFuture we had a lifespan removal occurring so it will be removed for sure
         return CompletableFutures.completedTrue();
      }
   }
141164
public void onCandidate(long sessionId, int index, String id, String sdp) {
        send(new RTCCandidate(deviceId, sessionId, index, id, sdp));
    }
525994
public void setMessageListener(MessageConsumer consumer, MessageListener listener) throws JMSException {
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "setMessageListener", new Object[]{consumer, listener});

    if (!(consumer instanceof JmsMsgConsumerImpl)) {
      // This "shouldn't happen" (tm) because the calling code switches on the class of the consumer.
      throw (JMSException) JmsErrorUtils.newThrowable(
          JMSException.class,
          "WRONG_CONSUMER_TYPE_CWSIA0088",
          new Object[] { consumer.getClass().getName() },
          null,
          "MessageListenerSetter.setMessageListener#1",
          this,
          tc);
    }

    JmsMsgConsumerImpl c = (JmsMsgConsumerImpl) consumer;

    boolean checkManaged = false;
    c._setMessageListener(listener, checkManaged);

    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "setMessageListener");
  }