@Override
  public void put(K k, V v, Metadata metadata) {
    boolean l1Entry = false;
    if (metadata instanceof L1Metadata) {
      metadata = ((L1Metadata) metadata).metadata();
      l1Entry = true;
    }
    InternalCacheEntry<K, V> e = entries.get(k);

    if (trace) {
      log.tracef(
          "Creating new ICE for writing. Existing=%s, metadata=%s, new value=%s",
          e, metadata, toStr(v));
    }
    final InternalCacheEntry<K, V> copy;
    if (l1Entry) {
      copy = entryFactory.createL1(k, v, metadata);
    } else if (e != null) {
      copy = entryFactory.update(e, v, metadata);
    } else {
      // this is a brand-new entry
      copy = entryFactory.create(k, v, metadata);
    }

    if (trace) log.tracef("Store %s in container", copy);

    entries.compute(
        copy.getKey(),
        (key, entry) -> {
          activator.onUpdate(key, entry == null);
          return copy;
        });
  }
 @Override
 public InternalCacheEntry<K, V> remove(Object k) {
   final InternalCacheEntry<K, V>[] reference = new InternalCacheEntry[1];
   entries.compute(
       (K) k,
       (key, entry) -> {
         activator.onRemove(key, entry == null);
         reference[0] = entry;
         return null;
       });
   InternalCacheEntry<K, V> e = reference[0];
   if (trace) {
     log.tracef("Removed %s from container", e);
   }
   return e == null || (e.canExpire() && e.isExpired(timeService.wallClockTime())) ? null : e;
 }
 @Override
 public InternalCacheEntry<K, V> compute(K key, ComputeAction<K, V> action) {
   return entries.compute(
       key,
       (k, oldEntry) -> {
         InternalCacheEntry<K, V> newEntry = action.compute(k, oldEntry, entryFactory);
         if (newEntry == oldEntry) {
           return oldEntry;
         } else if (newEntry == null) {
           activator.onRemove(k, false);
           return null;
         }
         activator.onUpdate(k, oldEntry == null);
         if (trace) log.tracef("Store %s in container", newEntry);
         return newEntry;
       });
 }
 @Override
 public void clear() {
   log.tracef("Clearing data container");
   entries.clear();
 }