| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal.cache; |
| |
| import static org.apache.geode.internal.offheap.annotations.OffHeapIdentifier.ABSTRACT_REGION_ENTRY_FILL_IN_VALUE; |
| import static org.apache.geode.internal.offheap.annotations.OffHeapIdentifier.ABSTRACT_REGION_ENTRY_PREPARE_VALUE_FOR_CACHE; |
| |
| import org.apache.geode.cache.CacheWriterException; |
| import org.apache.geode.cache.EntryEvent; |
| import org.apache.geode.cache.EntryNotFoundException; |
| import org.apache.geode.cache.TimeoutException; |
| import org.apache.geode.distributed.internal.DistributionManager; |
| import org.apache.geode.internal.InternalStatisticsDisabledException; |
| import org.apache.geode.internal.cache.InitialImageOperation.Entry; |
| import org.apache.geode.internal.cache.eviction.EvictionList; |
| import org.apache.geode.internal.cache.versions.VersionSource; |
| import org.apache.geode.internal.cache.versions.VersionStamp; |
| import org.apache.geode.internal.cache.versions.VersionTag; |
| import org.apache.geode.internal.offheap.StoredObject; |
| import org.apache.geode.internal.offheap.annotations.Released; |
| import org.apache.geode.internal.offheap.annotations.Retained; |
| import org.apache.geode.internal.offheap.annotations.Unretained; |
| import org.apache.geode.internal.serialization.ByteArrayDataInput; |
| import org.apache.geode.internal.serialization.KnownVersion; |
| |
| /** |
| * Internal interface for a region entry. Note that a region is implemented with a ConcurrentHashMap |
| * which has its own entry class. The "value" field of each of these entries will implement this |
| * interface. |
| * |
| * <p> |
| * Our RegionEntry does not need to keep a reference to the key. It is being referenced by the |
| * Map.Entry whose value field references this RegionEntry. |
| * |
| * @since GemFire 3.5.1 |
| */ |
| public interface RegionEntry { |
| |
| /** |
| * returns the time of last modification. Prior to v7.0 this only reflected creation time of an |
| * entry or the time it was last modified with an Update. In 7.0 and later releases it also |
| * reflects invalidate and destroy. |
| */ |
| long getLastModified(); |
| |
| /** |
| * Returns true if getLastAccessed, getHitCount, and getMissCount can be called without throwing |
| * InternalStatisticsDisabledException. Otherwise returns false. |
| * |
| * @since GemFire 6.0 |
| */ |
| boolean hasStats(); |
| |
| long getLastAccessed() throws InternalStatisticsDisabledException; |
| |
| /** |
| * Sets the entry's last accessed time if it has one. |
| */ |
| default void setLastAccessed(long lastAccessed) { |
| // do nothing by default |
| } |
| |
| long getHitCount() throws InternalStatisticsDisabledException; |
| |
| long getMissCount() throws InternalStatisticsDisabledException; |
| |
| void updateStatsForPut(long lastModifiedTime, long lastAccessedTime); |
| |
| /** |
| * @return the version information for this entry |
| */ |
| VersionStamp getVersionStamp(); |
| |
| /** |
| * @param member the member performing the change, or null if it's this member |
| * @param withDelta whether delta version information should be included |
| * @param region the owner of the region entry |
| * @param event the event causing this change |
| * @return a new version tag for this entry (null if versions not supported) |
| */ |
| VersionTag generateVersionTag(VersionSource member, boolean withDelta, InternalRegion region, |
| EntryEventImpl event); |
| |
| /** |
| * Dispatch listener events for the given entry event. If the event is from another member and |
| * there are already pending events, this will merely queue the event for later dispatch by one of |
| * those other events. |
| * |
| * This is done within the RegionEntry synchronization lock. |
| */ |
| boolean dispatchListenerEvents(EntryEventImpl event) throws InterruptedException; |
| |
| /** |
| * Used to mark an LRU entry as having been recently used. |
| */ |
| void setRecentlyUsed(RegionEntryContext context); // same method as on EvictionNode interface |
| |
| void updateStatsForGet(boolean hit, long time); |
| |
| /** |
| * Resets any entry state as needed for a transaction that did a destroy to this entry. |
| * |
| * @param currentTime Current Cache Time. |
| */ |
| void txDidDestroy(long currentTime); |
| |
| void resetCounts() throws InternalStatisticsDisabledException; |
| |
| /** |
| * this is done instead of removePhase2 if the entry needs to be kept for concurrency control |
| * |
| * @param region the region holding the entry |
| * @param version whether the operation is from another member or local |
| */ |
| void makeTombstone(InternalRegion region, VersionTag version) throws RegionClearedException; |
| |
| /** |
| * Mark this entry as being in the process of removal from the map that contains it by setting its |
| * value to Token.REMOVED_PHASE1. An entry in this state may be resurrected by changing the value |
| * under synchronization prior to the entry executing removePhase2. |
| * |
| * @param region the region |
| * @param clear - if we removing this entry as a result of a region clear. |
| * @throws RegionClearedException If operation got aborted due to a clear |
| * |
| */ |
| void removePhase1(InternalRegion region, boolean clear) throws RegionClearedException; |
| |
| /** |
| * Mark this entry as having been removed from the map that contained it by setting its value to |
| * Token.REMOVED_PHASE2 |
| */ |
| void removePhase2(); |
| |
| /** |
| * Returns true if this entry does not exist. This is true if removal has started (value == |
| * Token.REMOVED_PHASE1) or has completed (value == Token.REMOVED_PHASE2) or is a TOMBSTONE. |
| */ |
| boolean isRemoved(); |
| |
| /** |
| * Returns true if this entry does not exist and will not be resurrected (value == |
| * Token.REMOVED_PHASE2) |
| */ |
| boolean isRemovedPhase2(); |
| |
| /** |
| * Returns true if this entry is a tombstone, meaning that it has been removed but is being |
| * retained for concurrent modification detection. Tombstones may be resurrected just like an |
| * entry that is in REMOVED_PHASE1 state. |
| */ |
| boolean isTombstone(); |
| |
| /** |
| * Fill in value, and isSerialized fields in this entry object (used for getInitialImage and sync |
| * recovered) Also sets the lastModified time in cacheTime. Only called for DistributedRegions. |
| * |
| * <p> |
| * This method returns tombstones so that they can be transferred with the initial image. |
| * |
| * @return false if map entry not found |
| * |
| * @see InitialImageOperation.RequestImageMessage#chunkEntries |
| * |
| * @since GemFire 3.2.1 |
| */ |
| boolean fillInValue(InternalRegion region, |
| @Retained(ABSTRACT_REGION_ENTRY_FILL_IN_VALUE) Entry entry, ByteArrayDataInput in, |
| DistributionManager distributionManager, final KnownVersion version); |
| |
| /** |
| * Returns true if this entry has overflowed to disk. |
| * |
| * @param diskPosition if overflowed then the position of the value is set in dp |
| */ |
| boolean isOverflowedToDisk(InternalRegion region, DistributedRegion.DiskPosition diskPosition); |
| |
| /** |
| * Gets the key for this entry. |
| */ |
| Object getKey(); |
| |
| /** |
| * Gets the value for this entry. For DiskRegions, faults in value and returns it |
| */ |
| Object getValue(RegionEntryContext context); |
| |
| /** |
| * Just like getValue but the result may be a retained off-heap reference. |
| */ |
| @Retained |
| Object getValueRetain(RegionEntryContext context); |
| |
| @Released |
| void setValue(RegionEntryContext context, @Unretained Object value) throws RegionClearedException; |
| |
| /** |
| * This flavor of setValue was added so that the event could be passed down to Helper.writeToDisk. |
| * The event can be used to cache the serialized form of the value we are writing. See bug 43781. |
| */ |
| void setValue(RegionEntryContext context, Object value, EntryEventImpl event) |
| throws RegionClearedException; |
| |
| /** |
| * Obtain, retain and return the value of this entry. WARNING: if a StoredObject is returned and |
| * it has a refCount then the caller MUST make sure that {@link StoredObject#release()} before the |
| * returned object is garbage collected. |
| * |
| * This is only retained in off-heap subclasses. However, it's marked as Retained here so that |
| * callers are aware that the value may be retained. |
| * |
| * @param decompress if true returned value will be decompressed if it is compressed |
| * @return possible OFF_HEAP_OBJECT (caller must release) |
| */ |
| @Retained |
| Object getValueRetain(RegionEntryContext context, boolean decompress); |
| |
| /** |
| * Gets the value field of this entry. |
| */ |
| @Unretained |
| Object getValue(); |
| |
| /** |
| * Returns a tokenized form of the value. If the value can not be represented as a token then |
| * Token.NOT_A_TOKEN is returned. |
| */ |
| Token getValueAsToken(); |
| |
| /** |
| * Set the value of this entry and perform checks to see if a GC task needs to be scheduled. |
| * |
| * @param value the new value for this entry |
| * @param event the cache event that caused this change |
| * @throws RegionClearedException thrown if the region is concurrently cleared |
| */ |
| void setValueWithTombstoneCheck(@Unretained Object value, EntryEvent event) |
| throws RegionClearedException; |
| |
| /** |
| * Returns the value as stored by the RegionEntry implementation. For instance, if compressed this |
| * value would be the compressed form. |
| * |
| * @since GemFire 8.0 |
| */ |
| @Retained |
| Object getTransformedValue(); |
| |
| /** |
| * Returns the value of an entry as it resides in the VM. |
| * |
| * @return the value or EntryEvent.NOT_AVAILABLE token if it's not in the VM or null if the entry |
| * doesn't exist. |
| * |
| * @see InternalRegion#getValueInVM |
| */ |
| Object getValueInVM(RegionEntryContext context); |
| |
| /** |
| * Returns the value of an entry as it resides on disk. For testing purposes only. |
| * |
| * @see InternalRegion#getValueOnDisk |
| */ |
| Object getValueOnDisk(InternalRegion region) throws EntryNotFoundException; |
| |
| /** |
| * Returns the value of an entry as it resides on buffer or disk. For asynch mode a value is not |
| * immediately written to the disk & so checking in asynch buffers is needed .For testing purposes |
| * only. |
| * |
| * @see InternalRegion#getValueOnDisk |
| */ |
| |
| Object getValueOnDiskOrBuffer(InternalRegion region) throws EntryNotFoundException; |
| |
| |
| /** |
| * Used to modify an existing RegionEntry when processing the values obtained during a |
| * getInitialImage. |
| */ |
| boolean initialImagePut(InternalRegion region, long lastModified, Object newValue, |
| boolean wasRecovered, boolean acceptedVersionTag) throws RegionClearedException; |
| |
| /** |
| * Used to initialize a created RegionEntry when processing the values obtained during a |
| * getInitialImage. |
| * |
| * <p> |
| * put if LOCAL_INVALID and nonexistent<br> |
| * put if INVALID and nonexistent, recovered, or LOCAL_INVALID<br> |
| * put if valid and nonexistent, recovered, or LOCAL_INVALID |
| * |
| * <p> |
| * REGION_INVALIDATED: (special case)<br> |
| * If the region itself has been invalidated since getInitialImage<br> |
| * started, and newValue is LOCAL_INVALID or valid,<br> |
| * then force creation of INVALID key if currently nonexistent<br> |
| * or invalidate if current recovered.<br> |
| * |
| * <p> |
| * must write-synchronize to protect against puts from other<br> |
| * threads running this method |
| */ |
| boolean initialImageInit(InternalRegion region, long lastModified, Object newValue, |
| boolean create, boolean wasRecovered, boolean acceptedVersionTag) |
| throws RegionClearedException; |
| |
| /** |
| * @param expectedOldValue only succeed with destroy if current value is equal to expectedOldValue |
| * @param forceDestroy true if caller just added this entry because we are inTokenMode and we need |
| * to "create" a destroyed entry to mark the destroy |
| * @return true if destroy was done; false if not |
| */ |
| @Released |
| boolean destroy(InternalRegion region, EntryEventImpl event, boolean inTokenMode, |
| boolean cacheWrite, @Unretained Object expectedOldValue, boolean forceDestroy, |
| boolean removeRecoveredEntry) |
| throws CacheWriterException, EntryNotFoundException, TimeoutException, RegionClearedException; |
| |
| /** |
| * @return true if entry's value came from a netsearch |
| * @since GemFire 6.5 |
| */ |
| boolean getValueWasResultOfSearch(); |
| |
| /** |
| * @param value true if entry's value should be marked as having been the result of a netsearch. |
| * @since GemFire 6.5 |
| */ |
| void setValueResultOfSearch(boolean value); |
| |
| /** |
| * Get the serialized bytes from disk. This method only looks for the value on the disk, ignoring |
| * heap data. |
| * |
| * @param region the persistent region |
| * @return the serialized value from disk |
| * @since GemFire 5.7 |
| */ |
| Object getSerializedValueOnDisk(InternalRegion region); |
| |
| /** |
| * Gets the value for this entry. For DiskRegions, unlike {@link #getValue(RegionEntryContext)} |
| * this will not fault in the value rather return a temporary copy. |
| */ |
| Object getValueInVMOrDiskWithoutFaultIn(InternalRegion region); |
| |
| /** |
| * Gets the value for this entry. For DiskRegions, unlike {@link #getValue(RegionEntryContext)} |
| * this will not fault in the value rather return a temporary copy. The value returned will be |
| * kept off heap (and compressed) if possible. |
| */ |
| @Retained |
| Object getValueOffHeapOrDiskWithoutFaultIn(InternalRegion region); |
| |
| /** |
| * RegionEntry is underUpdate as soon as RegionEntry lock is help by an update thread to put a new |
| * value for an existing key. This is used during query on the region to verify index entry with |
| * current region entry. |
| * |
| * @return true if RegionEntry is under update during cache put operation. |
| */ |
| boolean isUpdateInProgress(); |
| |
| /** |
| * Sets RegionEntry updateInProgress flag when put is happening for an existing Region.Entry. |
| * Called ONLY in {@link AbstractRegionMap}. |
| */ |
| void setUpdateInProgress(final boolean underUpdate); |
| |
| /** |
| * Event containing this RegionEntry is being passed through dispatchListenerEvent for |
| * CacheListeners under RegionEntry lock. This is used during deserialization for a |
| * VMCacheSerializable value contained by this RegionEntry. |
| * |
| * @return true if Event is being dispatched to CacheListeners. |
| */ |
| boolean isCacheListenerInvocationInProgress(); |
| |
| /** |
| * Sets RegionEntry isCacheListenerInvoked flag when put is happening for a Region.Entry. Called |
| * ONLY in {@link InternalRegion#dispatchListenerEvent}. |
| */ |
| void setCacheListenerInvocationInProgress(final boolean isListenerInvoked); |
| |
| /** |
| * Returns true if the entry value is null. |
| */ |
| boolean isValueNull(); |
| |
| /** |
| * Returns true if the entry value is equal to {@link Token#INVALID} or |
| * {@link Token#LOCAL_INVALID}. |
| */ |
| boolean isInvalid(); |
| |
| /** |
| * Returns true if the entry value is equal to {@link Token#DESTROYED}. |
| */ |
| boolean isDestroyed(); |
| |
| /** |
| * Returns true if the entry value is equal to {@link Token#DESTROYED} or |
| * {@link Token#REMOVED_PHASE1} or {@link Token#REMOVED_PHASE2} or {@link Token#TOMBSTONE}. |
| */ |
| boolean isDestroyedOrRemoved(); |
| |
| /** |
| * Returns true if the entry value is equal to {@link Token#DESTROYED} or |
| * {@link Token#REMOVED_PHASE1} or {@link Token#REMOVED_PHASE2}. |
| */ |
| boolean isDestroyedOrRemovedButNotTombstone(); |
| |
| /** |
| * @see Token#isInvalidOrRemoved(Object) |
| */ |
| boolean isInvalidOrRemoved(); |
| |
| /** |
| * Sets the entry value to null. |
| */ |
| void setValueToNull(); |
| |
| void returnToPool(); |
| |
| boolean isInUseByTransaction(); |
| |
| /** |
| * Increments the number of transactions that are currently referencing this node. |
| */ |
| void incRefCount(); |
| |
| /** |
| * Decrements the number of transactions that are currently referencing this node. |
| * |
| * @param region the local region that owns this region entry; null if no local region owner |
| */ |
| void decRefCount(EvictionList lruList, InternalRegion region); |
| |
| /** |
| * Clear the number of transactions that are currently referencing this node and returns to LRU |
| * list |
| */ |
| void resetRefCount(EvictionList lruList); |
| |
| @Retained(ABSTRACT_REGION_ENTRY_PREPARE_VALUE_FOR_CACHE) |
| Object prepareValueForCache(RegionEntryContext context, Object value, boolean isEntryUpdate); |
| |
| @Retained(ABSTRACT_REGION_ENTRY_PREPARE_VALUE_FOR_CACHE) |
| Object prepareValueForCache(RegionEntryContext context, Object value, EntryEventImpl event, |
| boolean isEntryUpdate); |
| |
| boolean isEvicted(); |
| } |