package org.infinispan.metadata.impl; import static java.lang.Math.min; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Set; import org.infinispan.commons.marshall.AbstractExternalizer; import org.infinispan.commons.util.Util; import org.infinispan.container.entries.InternalCacheEntry; import org.infinispan.container.versioning.EntryVersion; import org.infinispan.marshall.core.Ids; import org.infinispan.metadata.InternalMetadata; import org.infinispan.metadata.Metadata; /** * @author Mircea Markus * @since 6.0 */ public class InternalMetadataImpl implements InternalMetadata { private final Metadata actual; private final long created; private final long lastUsed; public InternalMetadataImpl() { //required by the AZUL VM in order to run the tests this(null, -1, -1); } public InternalMetadataImpl(InternalCacheEntry ice) { this(ice.getMetadata(), ice.getCreated(), ice.getLastUsed()); } public InternalMetadataImpl(Metadata actual, long created, long lastUsed) { this.actual = extractMetadata(actual); this.created = created; this.lastUsed = lastUsed; } @Override public long lifespan() { return actual.lifespan(); } @Override public long maxIdle() { return actual.maxIdle(); } @Override public EntryVersion version() { return actual.version(); } @Override public Builder builder() { return actual.builder(); } @Override public long created() { return created; } @Override public long lastUsed() { return lastUsed; } public Metadata actual() { return actual; } @Override public long expiryTime() { long lifespan = actual.lifespan(); long lset = lifespan > -1 ? created + lifespan : -1; long maxIdle = actual.maxIdle(); long muet = maxIdle > -1 ? lastUsed + maxIdle : -1; if (lset == -1) return muet; if (muet == -1) return lset; return min(lset, muet); } @Override public boolean isExpired(long now) { long expiry = expiryTime(); return expiry > 0 && expiry <= now; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof InternalMetadataImpl)) return false; InternalMetadataImpl that = (InternalMetadataImpl) o; if (created != that.created) return false; if (lastUsed != that.lastUsed) return false; if (actual != null ? !actual.equals(that.actual) : that.actual != null) return false; return true; } @Override public int hashCode() { int result = actual != null ? actual.hashCode() : 0; result = 31 * result + (int) (created ^ (created >>> 32)); result = 31 * result + (int) (lastUsed ^ (lastUsed >>> 32)); return result; } @Override public String toString() { return "InternalMetadataImpl{" + "actual=" + actual + ", created=" + created + ", lastUsed=" + lastUsed + '}'; } private static Metadata extractMetadata(Metadata metadata) { Metadata toCheck = metadata; while (toCheck != null) { if (toCheck instanceof InternalMetadataImpl) { toCheck = ((InternalMetadataImpl) toCheck).actual(); } else { break; } } return toCheck; } public static class Externalizer extends AbstractExternalizer<InternalMetadataImpl> { private static final long serialVersionUID = -5291318076267612501L; public Externalizer() { } @Override public void writeObject(ObjectOutput output, InternalMetadataImpl b) throws IOException { output.writeLong(b.created); output.writeLong(b.lastUsed); output.writeObject(b.actual); } @Override public InternalMetadataImpl readObject(ObjectInput input) throws IOException, ClassNotFoundException { long created = input.readLong(); long lastUsed = input.readLong(); Metadata actual = (Metadata) input.readObject(); return new InternalMetadataImpl(actual, created, lastUsed); } @Override public Integer getId() { return Ids.INTERNAL_METADATA_ID; } @Override @SuppressWarnings("unchecked") public Set<Class<? extends InternalMetadataImpl>> getTypeClasses() { return Util.<Class<? extends InternalMetadataImpl>>asSet(InternalMetadataImpl.class); } } }