public void testUpdatingLastUsed() throws Exception {
    long idle = 600000;
    dc.put("k", "v", -1, -1);
    InternalCacheEntry ice = dc.get("k");
    assert ice.getClass().equals(immortaltype());
    assert ice.getExpiryTime() == -1;
    assert ice.getMaxIdle() == -1;
    assert ice.getLifespan() == -1;
    dc.put("k", "v", -1, idle);
    long oldTime = System.currentTimeMillis();
    Thread.sleep(100); // for time calc granularity
    ice = dc.get("k");
    assert ice.getClass().equals(transienttype());
    assert ice.getExpiryTime() > -1;
    assert ice.getLastUsed() > oldTime;
    Thread.sleep(100); // for time calc granularity
    assert ice.getLastUsed() < System.currentTimeMillis();
    assert ice.getMaxIdle() == idle;
    assert ice.getLifespan() == -1;

    oldTime = System.currentTimeMillis();
    Thread.sleep(100); // for time calc granularity
    assert dc.get("k") != null;

    // check that the last used stamp has been updated on a get
    assert ice.getLastUsed() > oldTime;
    Thread.sleep(100); // for time calc granularity
    assert ice.getLastUsed() < System.currentTimeMillis();
  }
 private void testStoredEntry(
     InternalCacheEntry entry,
     Object expectedValue,
     long expectedLifespan,
     String src,
     Object key) {
   assert entry != null : src + " entry for key " + key + " should NOT be null";
   assert entry.getValue().equals(expectedValue)
       : src
           + " should contain value "
           + expectedValue
           + " under key "
           + entry.getKey()
           + " but was "
           + entry.getValue()
           + ". Entry is "
           + entry;
   assert entry.getLifespan() == expectedLifespan
       : src
           + " expected lifespan for key "
           + key
           + " to be "
           + expectedLifespan
           + " but was "
           + entry.getLifespan()
           + ". Entry is "
           + entry;
 }
  private Object realRemoteGet(
      InvocationContext ctx, Object key, boolean storeInL1, boolean isWrite) throws Throwable {
    if (trace) log.tracef("Doing a remote get for key %s", key);

    boolean acquireRemoteLock = false;
    if (ctx.isInTxScope()) {
      TxInvocationContext txContext = (TxInvocationContext) ctx;
      acquireRemoteLock =
          isWrite && isPessimisticCache && !txContext.getAffectedKeys().contains(key);
    }
    // attempt a remote lookup
    InternalCacheEntry ice = dm.retrieveFromRemoteSource(key, ctx, acquireRemoteLock);

    if (acquireRemoteLock) {
      ((TxInvocationContext) ctx).addAffectedKey(key);
    }

    if (ice != null) {
      if (storeInL1) {
        if (isL1CacheEnabled) {
          if (trace) log.tracef("Caching remotely retrieved entry for key %s in L1", key);
          // This should be fail-safe
          try {
            long lifespan =
                ice.getLifespan() < 0
                    ? configuration.getL1Lifespan()
                    : Math.min(ice.getLifespan(), configuration.getL1Lifespan());
            PutKeyValueCommand put =
                cf.buildPutKeyValueCommand(
                    ice.getKey(), ice.getValue(), lifespan, -1, ctx.getFlags());
            lockAndWrap(ctx, key, ice);
            invokeNextInterceptor(ctx, put);
          } catch (Exception e) {
            // Couldn't store in L1 for some reason.  But don't fail the transaction!
            log.infof("Unable to store entry %s in L1 cache", key);
            log.debug("Inability to store in L1 caused by", e);
          }
        } else {
          CacheEntry ce = ctx.lookupEntry(key);
          if (ce == null || ce.isNull() || ce.isLockPlaceholder() || ce.getValue() == null) {
            if (ce != null && ce.isChanged()) {
              ce.setValue(ice.getValue());
            } else {
              if (isWrite) lockAndWrap(ctx, key, ice);
              else ctx.putLookedUpEntry(key, ice);
            }
          }
        }
      } else {
        if (trace) log.tracef("Not caching remotely retrieved entry for key %s in L1", key);
      }
      return ice.getValue();
    }
    return null;
  }
 @Override
 protected String toString(InternalCacheEntry ice) {
   if (ice == null) return null;
   StringBuilder sb = new StringBuilder(256);
   sb.append(ice.getClass().getSimpleName());
   sb.append("[key=").append(ice.getKey()).append(", value=").append(ice.getValue());
   sb.append(", created=").append(ice.getCreated()).append(", isCreated=").append(ice.isCreated());
   sb.append(", lastUsed=")
       .append(ice.getLastUsed())
       .append(", isChanged=")
       .append(ice.isChanged());
   sb.append(", expires=")
       .append(ice.getExpiryTime())
       .append(", isExpired=")
       .append(ice.isExpired(System.currentTimeMillis()));
   sb.append(", canExpire=")
       .append(ice.canExpire())
       .append(", isEvicted=")
       .append(ice.isEvicted());
   sb.append(", isRemoved=").append(ice.isRemoved()).append(", isValid=").append(ice.isValid());
   sb.append(", lifespan=")
       .append(ice.getLifespan())
       .append(", maxIdle=")
       .append(ice.getMaxIdle());
   return sb.append(']').toString();
 }
Example #5
0
 private MVCCEntry wrapInternalCacheEntryForPut(
     InvocationContext ctx, Object key, InternalCacheEntry cacheEntry) {
   MVCCEntry mvccEntry =
       createWrappedEntry(
           key,
           cacheEntry.getValue(),
           cacheEntry.getVersion(),
           false,
           false,
           cacheEntry.getLifespan());
   ctx.putLookedUpEntry(key, mvccEntry);
   return mvccEntry;
 }
 /**
  * Attempts to the L1 update and set the value. If the L1 update was marked as being skipped this
  * will instead just set the value to release blockers. A null value can be provided which will
  * not run the L1 update but will just alert other waiters that a null was given.
  */
 public void runL1UpdateIfPossible(InternalCacheEntry ice) {
   Object value = null;
   try {
     if (ice != null) {
       value = ice.getValue();
       Object key;
       if (sync.attemptUpdateToRunning() && !dc.containsKey((key = ice.getKey()))) {
         // Acquire the transfer lock to ensure that we don't have a rehash and change to become an
         // owner,
         // note we check the ownership in following if
         stateTransferLock.acquireSharedTopologyLock();
         try {
           // Now we can update the L1 if there isn't a value already there and we haven't now
           // become a write
           // owner
           if (!dc.containsKey(key) && !cdl.localNodeIsOwner(key)) {
             log.tracef("Caching remotely retrieved entry for key %s in L1", key);
             long lifespan =
                 ice.getLifespan() < 0 ? l1Lifespan : Math.min(ice.getLifespan(), l1Lifespan);
             // Make a copy of the metadata stored internally, adjust
             // lifespan/maxIdle settings and send them a modification
             Metadata newMetadata =
                 ice.getMetadata().builder().lifespan(lifespan).maxIdle(-1).build();
             dc.put(key, ice.getValue(), newMetadata);
           } else {
             log.tracef("Data container contained value after rehash for key %s", key);
           }
         } finally {
           stateTransferLock.releaseSharedTopologyLock();
         }
       }
     }
   } finally {
     sync.innerSet(value);
   }
 }
Example #7
0
 public Object getValueAt(int rowIndex, int columnIndex) {
   if (data.size() > rowIndex) {
     InternalCacheEntry e = data.get(rowIndex);
     switch (columnIndex) {
       case 0:
         return e.getKey();
       case 1:
         return e.getValue();
       case 2:
         return e.getLifespan();
       case 3:
         return e.getMaxIdle();
     }
   }
   return "NULL!";
 }
Example #8
0
  public void testIdleExpiryInPut() throws InterruptedException {
    Cache<String, String> cache = cm.getCache();
    long idleTime = IDLE_TIMEOUT;
    cache.put("k", "v", -1, MILLISECONDS, idleTime, MILLISECONDS);

    DataContainer dc = cache.getAdvancedCache().getDataContainer();
    InternalCacheEntry se = dc.get("k", null);
    assert se.getKey().equals("k");
    assert se.getValue().equals("v");
    assert se.getLifespan() == -1;
    assert se.getMaxIdle() == idleTime;
    assert !se.isExpired();
    assert cache.get("k").equals("v");
    Thread.sleep(idleTime + 100);
    assert se.isExpired();
    assert cache.get("k") == null;
  }
Example #9
0
  private void doApplyState(
      Address sender, int segmentId, Collection<InternalCacheEntry> cacheEntries) {
    log.debugf(
        "Applying new state for segment %d of cache %s from node %s: received %d cache entries",
        segmentId, cacheName, sender, cacheEntries.size());
    if (trace) {
      List<Object> keys = new ArrayList<Object>(cacheEntries.size());
      for (InternalCacheEntry e : cacheEntries) {
        keys.add(e.getKey());
      }
      log.tracef(
          "Received keys %s for segment %d of cache %s from node %s",
          keys, segmentId, cacheName, sender);
    }

    // CACHE_MODE_LOCAL avoids handling by StateTransferInterceptor and any potential locks in
    // StateTransferLock
    EnumSet<Flag> flags =
        EnumSet.of(
            PUT_FOR_STATE_TRANSFER,
            CACHE_MODE_LOCAL,
            IGNORE_RETURN_VALUES,
            SKIP_REMOTE_LOOKUP,
            SKIP_SHARED_CACHE_STORE,
            SKIP_OWNERSHIP_CHECK,
            SKIP_XSITE_BACKUP);
    for (InternalCacheEntry e : cacheEntries) {
      try {
        InvocationContext ctx;
        if (transactionManager != null) {
          // cache is transactional
          transactionManager.begin();
          Transaction transaction = transactionManager.getTransaction();
          ctx = icc.createInvocationContext(transaction);
          ((TxInvocationContext) ctx).setImplicitTransaction(true);
        } else {
          // non-tx cache
          ctx = icc.createSingleKeyNonTxInvocationContext();
        }

        PutKeyValueCommand put =
            useVersionedPut
                ? commandsFactory.buildVersionedPutKeyValueCommand(
                    e.getKey(),
                    e.getValue(),
                    e.getLifespan(),
                    e.getMaxIdle(),
                    e.getVersion(),
                    flags)
                : commandsFactory.buildPutKeyValueCommand(
                    e.getKey(), e.getValue(), e.getLifespan(), e.getMaxIdle(), flags);

        boolean success = false;
        try {
          interceptorChain.invoke(ctx, put);
          success = true;
        } finally {
          if (ctx.isInTxScope()) {
            if (success) {
              ((LocalTransaction) ((TxInvocationContext) ctx).getCacheTransaction())
                  .setFromStateTransfer(true);
              try {
                transactionManager.commit();
              } catch (Throwable ex) {
                log.errorf(
                    ex,
                    "Could not commit transaction created by state transfer of key %s",
                    e.getKey());
                if (transactionManager.getTransaction() != null) {
                  transactionManager.rollback();
                }
              }
            } else {
              transactionManager.rollback();
            }
          }
        }
      } catch (Exception ex) {
        log.problemApplyingStateForKey(ex.getMessage(), e.getKey(), ex);
      }
    }
    log.debugf("Finished applying state for segment %d of cache %s", segmentId, cacheName);
  }