| /* |
| * 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 java.io.DataInput; |
| import java.io.DataOutput; |
| import java.io.IOException; |
| |
| import org.apache.geode.DataSerializer; |
| import org.apache.geode.cache.CacheWriterException; |
| import org.apache.geode.cache.EntryEvent; |
| import org.apache.geode.cache.EntryNotFoundException; |
| import org.apache.geode.cache.Region; |
| import org.apache.geode.cache.StatisticsDisabledException; |
| import org.apache.geode.cache.TimeoutException; |
| import org.apache.geode.distributed.DistributedMember; |
| import org.apache.geode.distributed.internal.DistributionManager; |
| import org.apache.geode.distributed.internal.membership.InternalDistributedMember; |
| import org.apache.geode.internal.Assert; |
| 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.serialization.ByteArrayDataInput; |
| import org.apache.geode.internal.serialization.KnownVersion; |
| |
| public class NonLocalRegionEntry implements RegionEntry, VersionStamp { |
| |
| private long lastModified; |
| private boolean isRemoved; |
| private Object key; |
| private Object value; |
| private VersionTag versionTag; |
| |
| /** |
| * Create one of these in the local case so that we have a snapshot of the state and can allow the |
| * bucket to move out from under us. |
| */ |
| public NonLocalRegionEntry(RegionEntry re, InternalRegion br, boolean allowTombstones) { |
| this.key = re.getKey(); |
| if (allowTombstones && re.isTombstone()) { |
| // client get() operations need to see tombstone values |
| this.value = Token.TOMBSTONE; |
| } else { |
| this.value = re.getValue(br); // OFFHEAP: copy into heap cd |
| } |
| Assert.assertTrue(this.value != Token.NOT_AVAILABLE, |
| "getEntry did not fault value in from disk"); |
| this.lastModified = re.getLastModified(); |
| this.isRemoved = re.isRemoved(); |
| VersionStamp stamp = re.getVersionStamp(); |
| if (stamp != null) { |
| this.versionTag = stamp.asVersionTag(); |
| } |
| } |
| |
| /** |
| * Create one of these in the local case so that we have a snapshot of the state and can allow the |
| * bucket to move out from under us. |
| */ |
| public NonLocalRegionEntry(InternalRegion br, Object key, Object value) { |
| this.key = key; |
| this.value = value; |
| Assert.assertTrue(this.value != Token.NOT_AVAILABLE, |
| "getEntry did not fault value in from disk"); |
| } |
| |
| /** |
| * Create one of these in the local case so that we have a snapshot of the state and can allow the |
| * bucket to move out from under us. |
| */ |
| public NonLocalRegionEntry(Region.Entry re, InternalRegion br) { |
| this.key = re.getKey(); |
| this.value = re.getValue(); |
| if (this.value instanceof CachedDeserializable) { |
| // We make a copy of the CachedDeserializable. |
| // That way the NonLocalRegionEntry will be disconnected |
| // from the CachedDeserializable that is in our cache and |
| // will not modify its state. |
| this.value = CachedDeserializableFactory.create((CachedDeserializable) this.value); |
| } |
| Assert.assertTrue(this.value != Token.NOT_AVAILABLE, |
| "getEntry did not fault value in from disk"); |
| this.lastModified = 0l;// re.getStatistics().getLastModifiedTime(); |
| this.isRemoved = Token.isRemoved(value); |
| if (re instanceof EntrySnapshot) { |
| this.versionTag = ((EntrySnapshot) re).getVersionTag(); |
| } else { |
| // TODO need to get version information from transaction entries |
| } |
| } |
| |
| @Override |
| public String toString() { |
| return "NonLocalRegionEntry(" + this.key + "; value=" + this.value + "; version=" |
| + this.versionTag; |
| } |
| |
| @Override |
| public void makeTombstone(InternalRegion region, VersionTag version) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean dispatchListenerEvents(EntryEventImpl event) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public VersionStamp getVersionStamp() { |
| return this; |
| } |
| |
| @Override |
| public boolean hasValidVersion() { |
| return this.versionTag != null && this.versionTag.hasValidVersion(); |
| } |
| |
| @Override |
| public void setVersionTimeStamp(long time) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void processVersionTag(EntryEvent event) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public NonLocalRegionEntry() { |
| // for fromData |
| } |
| |
| public void toData(DataOutput out) throws IOException { |
| DataSerializer.writeObject(this.key, out); |
| DataSerializer.writeObject(this.value, out); |
| out.writeLong(this.lastModified); |
| out.writeBoolean(this.isRemoved); |
| DataSerializer.writeObject(this.versionTag, out); |
| } |
| |
| public void fromData(DataInput in) throws IOException, ClassNotFoundException { |
| this.key = DataSerializer.readObject(in); |
| this.value = DataSerializer.readObject(in); |
| this.lastModified = in.readLong(); |
| this.isRemoved = in.readBoolean(); |
| this.versionTag = (VersionTag) DataSerializer.readObject(in); |
| } |
| |
| @Override |
| public long getLastModified() { |
| return this.lastModified; |
| } |
| |
| @Override |
| public long getLastAccessed() throws StatisticsDisabledException { |
| return -1; |
| } |
| |
| @Override |
| public long getHitCount() throws StatisticsDisabledException { |
| return -1; |
| } |
| |
| @Override |
| public long getMissCount() throws StatisticsDisabledException { |
| return -1; |
| } |
| |
| @Override |
| public boolean isRemoved() { |
| return this.isRemoved; |
| } |
| |
| @Override |
| public boolean isRemovedPhase2() { |
| return this.isRemoved; |
| } |
| |
| @Override |
| public boolean isTombstone() { |
| return false; |
| } |
| |
| @Override |
| public boolean fillInValue(InternalRegion region, Entry entry, ByteArrayDataInput in, |
| DistributionManager distributionManager, final KnownVersion version) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isOverflowedToDisk(InternalRegion region, |
| DistributedRegion.DiskPosition diskPosition) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getKey() { |
| return this.key; |
| } |
| |
| @Override |
| public Object getValue(RegionEntryContext context) { |
| return this.value; |
| } |
| |
| @Override |
| public Object getValueRetain(RegionEntryContext context) { |
| return this.value; |
| } |
| |
| /** update the value held in this non-local region entry */ |
| void setCachedValue(Object newValue) { |
| this.value = newValue; |
| } |
| |
| // now for the fun part |
| @Override |
| public void updateStatsForPut(long lastModifiedTime, long lastAccessedTime) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void setRecentlyUsed(RegionEntryContext context) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void updateStatsForGet(boolean hit, long time) throws StatisticsDisabledException { |
| // this method has been made a noop to fix bug 37436 |
| } |
| |
| @Override |
| public void txDidDestroy(long currentTime) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void resetCounts() throws StatisticsDisabledException { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void removePhase1(InternalRegion region, boolean clear) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void removePhase2() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void setValue(RegionEntryContext context, Object value) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getValue() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Token getValueAsToken() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getValueRetain(RegionEntryContext context, boolean decompress) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getTransformedValue() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getValueInVM(RegionEntryContext context) { |
| return this.value; |
| } |
| |
| @Override |
| public Object getValueOnDisk(InternalRegion region) throws EntryNotFoundException { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean initialImagePut(InternalRegion region, long lastModified, Object newValue, |
| boolean wasRecovered, boolean acceptedVersionTag) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean initialImageInit(InternalRegion region, long lastModified, Object newValue, |
| boolean create, boolean wasRecovered, boolean acceptedVersionTag) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean destroy(InternalRegion region, EntryEventImpl event, boolean inTokenMode, |
| boolean cacheWrite, Object expectedOldValue, boolean forceDestroy, |
| boolean removeRecoveredEntry) |
| throws CacheWriterException, EntryNotFoundException, TimeoutException { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean getValueWasResultOfSearch() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void setValueResultOfSearch(boolean value) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getValueOnDiskOrBuffer(InternalRegion region) throws EntryNotFoundException { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public Object getSerializedValueOnDisk(InternalRegion region) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| |
| @Override |
| public boolean hasStats() { |
| return false; |
| } |
| |
| @Override |
| public Object getValueInVMOrDiskWithoutFaultIn(InternalRegion region) { |
| return this.value; |
| } |
| |
| @Override |
| public Object getValueOffHeapOrDiskWithoutFaultIn(InternalRegion region) { |
| return this.value; |
| } |
| |
| public void setKey(Object key2) { |
| this.key = key2; |
| } |
| |
| @Override |
| public VersionTag generateVersionTag(VersionSource member, boolean withDelta, |
| InternalRegion region, EntryEventImpl event) { |
| throw new UnsupportedOperationException(); // no text needed - not a customer visible method |
| } |
| |
| public void processVersionTag(InternalRegion r, VersionTag tag, InternalDistributedMember thisVM, |
| InternalDistributedMember sender) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int getEntryVersion() { |
| if (this.versionTag != null) { |
| return this.versionTag.getEntryVersion(); |
| } |
| return 0; |
| } |
| |
| @Override |
| public long getRegionVersion() { |
| if (this.versionTag != null) { |
| return this.versionTag.getRegionVersion(); |
| } |
| return 0; |
| } |
| |
| @Override |
| public VersionSource getMemberID() { |
| if (this.versionTag != null) { |
| return this.versionTag.getMemberID(); |
| } |
| return null; |
| } |
| |
| @Override |
| public int getDistributedSystemId() { |
| if (this.versionTag != null) { |
| return this.versionTag.getDistributedSystemId(); |
| } |
| return -1; |
| } |
| |
| @Override |
| public void setVersions(VersionTag tag) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void setMemberID(VersionSource memberID) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void setPreviousMemberID(DistributedMember previousMemberID) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public VersionTag asVersionTag() { |
| return this.versionTag; |
| } |
| |
| @Override |
| public void processVersionTag(InternalRegion region, VersionTag tag, boolean isTombstoneFromGII, |
| boolean hasDelta, VersionSource versionSource, InternalDistributedMember sender, |
| boolean checkConflicts) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public long getVersionTimeStamp() { |
| return this.versionTag != null ? this.versionTag.getVersionTimeStamp() : 0; |
| } |
| |
| /** get rvv internal high byte. Used by region entries for transferring to storage */ |
| @Override |
| public short getRegionVersionHighBytes() { |
| return this.versionTag != null ? this.versionTag.getRegionVersionHighBytes() : 0; |
| } |
| |
| /** get rvv internal low bytes. Used by region entries for transferring to storage */ |
| @Override |
| public int getRegionVersionLowBytes() { |
| return this.versionTag != null ? this.versionTag.getRegionVersionLowBytes() : 0; |
| } |
| |
| @Override |
| public boolean isUpdateInProgress() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void setUpdateInProgress(boolean underUpdate) { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isValueNull() { |
| return (null == getValueAsToken()); |
| } |
| |
| @Override |
| public boolean isInvalid() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isDestroyed() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void setValueToNull() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isInvalidOrRemoved() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isDestroyedOrRemoved() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isDestroyedOrRemovedButNotTombstone() { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public void returnToPool() { |
| // nothing |
| } |
| |
| @Override |
| public void setValueWithTombstoneCheck(Object value, EntryEvent event) |
| throws RegionClearedException { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isCacheListenerInvocationInProgress() { |
| return false; |
| } |
| |
| @Override |
| public void setCacheListenerInvocationInProgress(boolean isListenerInvoked) { |
| // nothing |
| } |
| |
| @Override |
| public void setValue(RegionEntryContext context, Object value, EntryEventImpl event) |
| throws RegionClearedException { |
| throw new UnsupportedOperationException( |
| "Not appropriate for PartitionedRegion.NonLocalRegionEntry"); |
| } |
| |
| @Override |
| public boolean isInUseByTransaction() { |
| return false; |
| } |
| |
| @Override |
| public void incRefCount() { |
| // nothing |
| } |
| |
| @Override |
| public void decRefCount(EvictionList lruList, InternalRegion region) { |
| // nothing |
| } |
| |
| @Override |
| public void resetRefCount(EvictionList lruList) { |
| // nothing |
| } |
| |
| @Override |
| public Object prepareValueForCache(RegionEntryContext context, Object value, |
| boolean isEntryUpdate) { |
| throw new IllegalStateException("Should never be called"); |
| } |
| |
| @Override |
| public Object prepareValueForCache(RegionEntryContext context, Object value, EntryEventImpl event, |
| boolean isEntryUpdate) { |
| throw new IllegalStateException("Should never be called"); |
| } |
| |
| @Override |
| public boolean isEvicted() { |
| return false; |
| } |
| } |