/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.internal.nearcache.impl.record; import com.hazelcast.internal.nearcache.NearCacheRecord; import java.util.UUID; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; /** * Abstract implementation of {@link NearCacheRecord} with value and expiration time as internal state. * * @param <V> the type of the value stored by this {@link AbstractNearCacheRecord} */ public abstract class AbstractNearCacheRecord<V> implements NearCacheRecord<V> { // primitive long typed fields: // "creationTime", "expirationTime" and "accessTime", "recordState", "sequence" public static final int NUMBER_OF_LONG_FIELD_TYPES = 5; // primitive int typed fields: "accessHit" public static final int NUMBER_OF_INTEGER_FIELD_TYPES = 1; private static final AtomicIntegerFieldUpdater<AbstractNearCacheRecord> ACCESS_HIT = AtomicIntegerFieldUpdater.newUpdater(AbstractNearCacheRecord.class, "accessHit"); private static final AtomicLongFieldUpdater<AbstractNearCacheRecord> RECORD_STATE = AtomicLongFieldUpdater.newUpdater(AbstractNearCacheRecord.class, "recordState"); protected long creationTime = TIME_NOT_SET; protected long sequence; protected UUID uuid; protected volatile V value; protected volatile long expirationTime = TIME_NOT_SET; protected volatile long accessTime = TIME_NOT_SET; protected volatile long recordState = READ_PERMITTED; protected volatile int accessHit; public AbstractNearCacheRecord(V value, long creationTime, long expirationTime) { this.value = value; this.creationTime = creationTime; this.expirationTime = expirationTime; } @Override public V getValue() { return value; } @Override public void setValue(V value) { this.value = value; } @Override public long getExpirationTime() { return expirationTime; } @Override public void setExpirationTime(long expirationTime) { this.expirationTime = expirationTime; } @Override public long getCreationTime() { return creationTime; } @Override public void setCreationTime(long creationTime) { this.creationTime = creationTime; } @Override public long getLastAccessTime() { return accessTime; } @Override public void setAccessTime(long accessTime) { this.accessTime = accessTime; } @Override public int getAccessHit() { return accessHit; } @Override public void setAccessHit(int accessHit) { ACCESS_HIT.set(this, accessHit); } @Override public void incrementAccessHit() { ACCESS_HIT.addAndGet(this, 1); } @Override public void resetAccessHit() { ACCESS_HIT.set(this, 0); } @Override public boolean isExpiredAt(long now) { return (expirationTime > TIME_NOT_SET) && (expirationTime <= now); } @Override public long getInvalidationSequence() { return sequence; } @Override public void setInvalidationSequence(long sequence) { this.sequence = sequence; } @Override public boolean hasSameUuid(UUID thatUuid) { if (uuid == null || thatUuid == null) { return false; } return uuid.equals(thatUuid); } @Override public void setUuid(UUID uuid) { this.uuid = uuid; } @Override public boolean isIdleAt(long maxIdleMilliSeconds, long now) { if (maxIdleMilliSeconds > 0) { if (accessTime > TIME_NOT_SET) { return accessTime + maxIdleMilliSeconds < now; } else { return creationTime + maxIdleMilliSeconds < now; } } else { return false; } } @Override public long getRecordState() { return recordState; } @Override public boolean casRecordState(long expect, long update) { return RECORD_STATE.compareAndSet(this, expect, update); } @Override public String toString() { return "creationTime=" + creationTime + ", sequence=" + sequence + ", uuid=" + uuid + ", expirationTime=" + expirationTime + ", accessTime=" + accessTime + ", accessHit=" + accessHit + ", recordState=" + recordState + ", value=" + value; } }