This is an automated email from the ASF dual-hosted git repository. jbarrett pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push: new 80aabee GEODE-5305: Add flag to TXCommitMessage to indicate the use of shadow key (#2043) 80aabee is described below commit 80aabeede64c81f92437bc1c8be11a4000ed43e2 Author: Jacob Barrett <jbarr...@pivotal.io> AuthorDate: Wed Jun 13 10:20:07 2018 -0700 GEODE-5305: Add flag to TXCommitMessage to indicate the use of shadow key (#2043) * Add new unit test for TxCommentMessage serialization. Co-authored-by: Darrel Schneider <dschnei...@pivotal.io> --- .../geode/internal/InternalDataSerializer.java | 125 ++- .../geode/internal/cache/TXCommitMessage.java | 230 ++-- .../apache/geode/internal/cache/TXRegionState.java | 4 - .../geode/internal/cache/TxCommitMessageTest.java | 1167 ++++++++++++++++++++ .../codeAnalysis/sanctionedDataSerializables.txt | 8 +- 5 files changed, 1363 insertions(+), 171 deletions(-) diff --git a/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java b/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java index 7ab6284..94aea2c 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java +++ b/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java @@ -141,23 +141,22 @@ public abstract class InternalDataSerializer extends DataSerializer { /** - * This list contains classes that Geode's classes subclass, such as antlr AST classes which - * are used by our Object Query Language. It also contains certain - * classes that are DataSerializable but end up being serialized as part of other serializable - * objects. VersionedObjectList, for instance, is serialized as part of a - * partial putAll exception object. + * This list contains classes that Geode's classes subclass, such as antlr AST classes which are + * used by our Object Query Language. It also contains certain classes that are DataSerializable + * but end up being serialized as part of other serializable objects. VersionedObjectList, for + * instance, is serialized as part of a partial putAll exception object. * <p> - * Do not java-serialize objects that Geode does not have complete control over. This - * leaves us open to security attacks such as Gadget Chains and compromises the ability - * to do a rolling upgrade from one version of Geode to the next. + * Do not java-serialize objects that Geode does not have complete control over. This leaves us + * open to security attacks such as Gadget Chains and compromises the ability to do a rolling + * upgrade from one version of Geode to the next. * <p> * In general you shouldn't use java serialization and you should implement - * DataSerializableFixedID - * for internal Geode objects. This gives you better control over backward-compatibility. + * DataSerializableFixedID for internal Geode objects. This gives you better control over + * backward-compatibility. * <p> - * Do not add to this list unless absolutely necessary. Instead put your classes either - * in the sanctionedSerializables file for your module or in its excludedClasses file. - * Run AnalyzeSerializables to generate the content for the file. + * Do not add to this list unless absolutely necessary. Instead put your classes either in the + * sanctionedSerializables file for your module or in its excludedClasses file. Run + * AnalyzeSerializables to generate the content for the file. * <p> */ private static final String SANCTIONED_SERIALIZABLES_DEPENDENCIES_PATTERN = @@ -798,8 +797,8 @@ public abstract class InternalDataSerializer extends DataSerializer { new ConcurrentHashMap<>(); /** - * {@code RegistrationListener}s that receive callbacks when {@code DataSerializer}s and - * {@code Instantiator}s are registered. Note: copy-on-write access used for this set + * {@code RegistrationListener}s that receive callbacks when {@code DataSerializer}s and {@code + * Instantiator}s are registered. Note: copy-on-write access used for this set */ private static volatile Set listeners = new HashSet(); @@ -825,7 +824,6 @@ public abstract class InternalDataSerializer extends DataSerializer { * Instantiates an instance of {@code DataSerializer} * * @throws IllegalArgumentException If the class can't be instantiated - * * @see DataSerializer#register(Class) */ static DataSerializer newInstance(Class c) { @@ -843,7 +841,8 @@ public abstract class InternalDataSerializer extends DataSerializer { StringId s = LocalizedStrings.DataSerializer_CLASS_0_DOES_NOT_HAVE_A_ZEROARGUMENT_CONSTRUCTOR; Object[] args = new Object[] {c.getName()}; if (c.getDeclaringClass() != null) { - s = LocalizedStrings.DataSerializer_CLASS_0_DOES_NOT_HAVE_A_ZEROARGUMENT_CONSTRUCTOR_IT_IS_AN_INNER_CLASS_OF_1_SHOULD_IT_BE_A_STATIC_INNER_CLASS; + s = + LocalizedStrings.DataSerializer_CLASS_0_DOES_NOT_HAVE_A_ZEROARGUMENT_CONSTRUCTOR_IT_IS_AN_INNER_CLASS_OF_1_SHOULD_IT_BE_A_STATIC_INNER_CLASS; args = new Object[] {c.getName(), c.getDeclaringClass()}; } throw new IllegalArgumentException(s.toLocalizedString(args)); @@ -889,7 +888,6 @@ public abstract class InternalDataSerializer extends DataSerializer { * * @param distribute Should the registered {@code DataSerializer} be distributed to other members * of the distributed system? - * * @see DataSerializer#register(Class) */ public static DataSerializer register(Class c, boolean distribute) { @@ -1018,8 +1016,8 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * Marks a {@code DataSerializer} className for registration with the data serialization - * framework if and when it is needed. Does not necessarily load the classes into this VM. + * Marks a {@code DataSerializer} className for registration with the data serialization framework + * if and when it is needed. Does not necessarily load the classes into this VM. * * @param className Name of the DataSerializer class. * @param distribute If true, distribute this data serializer. @@ -1074,10 +1072,10 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * During client/server handshakes the server may send a collection of DataSerializers and - * the classes they support. The DataSerializers are registered as "holders" to avoid loading the - * actual classes until they're needed. This method registers the names of classes supported - * by the DataSerializers + * During client/server handshakes the server may send a collection of DataSerializers and the + * classes they support. The DataSerializers are registered as "holders" to avoid loading the + * actual classes until they're needed. This method registers the names of classes supported by + * the DataSerializers * * @param map The classes returned by DataSerializer.supportedClasses() */ @@ -1100,10 +1098,10 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * A SerializerAttributesHolder holds information required to load a DataSerializer - * and exists to allow client/server connections to be created more quickly than - * they would if the DataSerializer information downloaded from the server were - * used to immediately load the corresponding classes. + * A SerializerAttributesHolder holds information required to load a DataSerializer and exists to + * allow client/server connections to be created more quickly than they would if the + * DataSerializer information downloaded from the server were used to immediately load the + * corresponding classes. */ public static class SerializerAttributesHolder { private String className = ""; @@ -1121,7 +1119,6 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * * @return String the classname of the data serializer this instance represents. */ public String getClassName() { @@ -1230,10 +1227,9 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * Returns the {@code DataSerializer} for the given class. If no class has been registered, - * {@code null} is returned. Remember that it is okay to return {@code null} in this case. This - * method is invoked when writing an object. If a serializer isn't available, then its the user's - * fault. + * Returns the {@code DataSerializer} for the given class. If no class has been registered, {@code + * null} is returned. Remember that it is okay to return {@code null} in this case. This method is + * invoked when writing an object. If a serializer isn't available, then its the user's fault. */ private static DataSerializer getSerializer(Class c) { DataSerializer ds = classesToSerializers.get(c.getName()); @@ -1813,14 +1809,11 @@ public abstract class InternalDataSerializer extends DataSerializer { /** * Writes a {@code Set} to a {@code DataOutput}. * <P> - * This method is internal because its semantics (that is, its ability to write any kind of - * {@code Set}) are different from the {@code write}XXX methods of the external - * {@code DataSerializer}. + * This method is internal because its semantics (that is, its ability to write any kind of {@code + * Set}) are different from the {@code write}XXX methods of the external {@code DataSerializer}. * * @throws IOException A problem occurs while writing to {@code out} - * * @see #readSet - * * @since GemFire 4.0 */ public static void writeSet(Collection<?> set, DataOutput out) throws IOException { @@ -1849,9 +1842,7 @@ public abstract class InternalDataSerializer extends DataSerializer { * @throws IOException A problem occurs while writing to {@code out} * @throws ClassNotFoundException The class of one of the {@code HashSet}'s elements cannot be * found. - * * @see #writeSet - * * @since GemFire 4.0 */ public static Set readSet(DataInput in) throws IOException, ClassNotFoundException { @@ -1864,7 +1855,6 @@ public abstract class InternalDataSerializer extends DataSerializer { * * @throws IOException A problem occurs while reading from {@code in} * @throws ClassNotFoundException The class of one of the {@code Set}'s elements cannot be found. - * * @see #writeSet */ public static <E> boolean readCollection(DataInput in, Collection<E> c) @@ -1912,7 +1902,9 @@ public abstract class InternalDataSerializer extends DataSerializer { } } - /** read a set of Long objects */ + /** + * read a set of Long objects + */ public static Set<Long> readSetOfLongs(DataInput in) throws IOException { int size = in.readInt(); if (size < 0) { @@ -1953,7 +1945,9 @@ public abstract class InternalDataSerializer extends DataSerializer { } } - /** read a set of Long objects */ + /** + * read a set of Long objects + */ public static List<Long> readListOfLongs(DataInput in) throws IOException { int size = in.readInt(); if (size < 0) { @@ -1970,7 +1964,6 @@ public abstract class InternalDataSerializer extends DataSerializer { } - /** * Writes the type code for a primitive type Class to {@code DataOutput}. */ @@ -2175,7 +2168,6 @@ public abstract class InternalDataSerializer extends DataSerializer { * Writes given number of characters from array of {@code char}s to a {@code DataOutput}. * * @throws IOException A problem occurs while writing to {@code out} - * * @see DataSerializer#readCharArray * @since GemFire 6.6 */ @@ -2484,7 +2476,8 @@ public abstract class InternalDataSerializer extends DataSerializer { // error condition, so you also need to check to see if the JVM // is still usable: SystemFailure.checkFailure(); - throw new ToDataException("toData failed on DataSerializable " + ds.getClass(), t); + throw new ToDataException( + "toData failed on DataSerializable " + null == ds ? "null" : ds.getClass().toString(), t); } } @@ -2702,7 +2695,8 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * Serializes a list of Integers. The argument may be null. Deserialize with readListOfIntegers(). + * Serializes a list of Integers. The argument may be null. Deserialize with + * readListOfIntegers(). * * TODO: writeListOfIntegers is unused */ @@ -2762,7 +2756,6 @@ public abstract class InternalDataSerializer extends DataSerializer { * being read. The return value may be {@code null}. * * @throws IOException A problem occurs while reading from {@code in} - * * @since GemFire 5.7 */ public static String readString(DataInput in, byte header) throws IOException { @@ -3341,10 +3334,14 @@ public abstract class InternalDataSerializer extends DataSerializer { * wait an amount of time for the registration message to arrive. */ abstract static class Marker { - /** The DataSerializer that is filled in upon registration */ + /** + * The DataSerializer that is filled in upon registration + */ protected DataSerializer serializer = null; - /** set to true once setSerializer is called. */ + /** + * set to true once setSerializer is called. + */ boolean hasBeenSet = false; abstract DataSerializer getSerializer(); @@ -3361,6 +3358,7 @@ public abstract class InternalDataSerializer extends DataSerializer { } } } + /** * A marker object for {@code DataSerializer}s that have not been registered. Using this marker * object allows us to asynchronously send {@code DataSerializer} registration updates. If the @@ -3426,6 +3424,7 @@ public abstract class InternalDataSerializer extends DataSerializer { * yet, then this method will wait until the serializer is registered. If this method has to * wait for too long, then {@code null} is returned. */ + /** * Returns the serializer associated with this marker. Waits forever (unless interrupted) for it * to be initialized. Returns null if this Marker failed to initialize. @@ -3446,9 +3445,10 @@ public abstract class InternalDataSerializer extends DataSerializer { } } } + /** - * A distribution message that alerts other members of the distributed cache of a new - * {@code DataSerializer} being registered. + * A distribution message that alerts other members of the distributed cache of a new {@code + * DataSerializer} being registered. */ public static class RegistrationMessage extends SerialDistributionMessage { /** @@ -3461,10 +3461,14 @@ public abstract class InternalDataSerializer extends DataSerializer { */ protected EventID eventId; - /** The name of the {@code DataSerializer} class */ + /** + * The name of the {@code DataSerializer} class + */ private String className; - /** The versions in which this message was modified */ + /** + * The versions in which this message was modified + */ private static final Version[] dsfidVersions = new Version[] {}; /** @@ -3473,8 +3477,8 @@ public abstract class InternalDataSerializer extends DataSerializer { public RegistrationMessage() {} /** - * Creates a new {@code RegistrationMessage} that broadcasts that the given - * {@code DataSerializer} was registered. + * Creates a new {@code RegistrationMessage} that broadcasts that the given {@code + * DataSerializer} was registered. */ public RegistrationMessage(DataSerializer s) { this.className = s.getClass().getName(); @@ -3588,8 +3592,8 @@ public abstract class InternalDataSerializer extends DataSerializer { } /** - * A listener whose listener methods are invoked when {@link DataSerializer}s and - * {@link Instantiator}s are registered. This is part of the fix for bug 31422. + * A listener whose listener methods are invoked when {@link DataSerializer}s and {@link + * Instantiator}s are registered. This is part of the fix for bug 31422. * * @see InternalDataSerializer#addRegistrationListener * @see InternalDataSerializer#removeRegistrationListener @@ -3616,8 +3620,8 @@ public abstract class InternalDataSerializer extends DataSerializer { private static class DSObjectInputStream extends ObjectInputStream { /** - * Creates a new {@code DSObjectInputStream} that delegates its behavior to a given - * {@code InputStream}. + * Creates a new {@code DSObjectInputStream} that delegates its behavior to a given {@code + * InputStream}. */ DSObjectInputStream(InputStream stream) throws IOException { super(stream); @@ -3708,7 +3712,6 @@ public abstract class InternalDataSerializer extends DataSerializer { /** * Just like a WellKnownDS but its type is compatible with PDX. - * */ protected abstract static class WellKnownPdxDS extends WellKnownDS { // subclasses need to implement toData diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java index 8354430..722130e 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java @@ -115,10 +115,14 @@ public class TXCommitMessage extends PooledDistributionMessage private transient long farsideBaseThreadId; // only available on farside private transient long farsideBaseSequenceId; // only available on farside - /** (Nearside) true of any regions in this TX have required roles */ + /** + * (Nearside) true of any regions in this TX have required roles + */ private transient boolean hasReliableRegions = false; - /** Set of all caching exceptions produced hile processing this tx */ + /** + * Set of all caching exceptions produced hile processing this tx + */ private transient Set processingExceptions = Collections.emptySet(); private transient ClientProxyMembershipID bridgeContext = null; @@ -136,7 +140,8 @@ public class TXCommitMessage extends PooledDistributionMessage public static final TXCommitMessage CMT_CONFLICT_MSG = new TXCommitMessage(); /** * A token to be put in TXManagerImpl#failoverMap to represent a - * TransactionDataNodeHasDepartedException while committing a transaction + * TransactionDataNodeHasDepartedException + * while committing a transaction */ public static final TXCommitMessage REBALANCE_MSG = new TXCommitMessage(); /** @@ -200,7 +205,7 @@ public class TXCommitMessage extends PooledDistributionMessage // make sure we have some changes and someone to send them to if (!this.currentRegion.isEmpty() && s != null && !s.isEmpty()) { // Get the persistent ids for the current region and save them - this.currentRegion.persistentIds = getPersistentIds(this.currentRegion.r); + this.currentRegion.persistentIds = getPersistentIds(this.currentRegion.internalRegion); if (this.msgMap == null) { this.msgMap = new HashMap<>(); @@ -279,7 +284,9 @@ public class TXCommitMessage extends PooledDistributionMessage private transient boolean disableListeners = false; - /** record CacheDistributionAdvisor.startOperation versions for later cleanup */ + /** + * record CacheDistributionAdvisor.startOperation versions for later cleanup + */ protected void addViewVersion(DistributedRegion dr, long version) { viewVersions.put(dr, version); } @@ -323,7 +330,7 @@ public class TXCommitMessage extends PooledDistributionMessage updateLockMembers(); IdentityHashMap distMap = new IdentityHashMap(); // Map of RegionCommitList keys to Sets of - // receivers + // receivers HashSet ackReceivers = null; { Iterator it = this.msgMap.entrySet().iterator(); @@ -450,7 +457,7 @@ public class TXCommitMessage extends PooledDistributionMessage for (Iterator rclIter = rcl.iterator(); rclIter.hasNext();) { RegionCommit rc = (RegionCommit) rclIter.next(); // skip region if no required roles - if (!rc.r.requiresReliabilityCheck()) { + if (!rc.internalRegion.requiresReliabilityCheck()) { continue; } @@ -484,20 +491,20 @@ public class TXCommitMessage extends PooledDistributionMessage // remove members who destroyed that region or closed their cache Set regionDestroyedMembers = (processor == null) ? Collections.emptySet() - : processor.getRegionDestroyedMembers(rc.r.getFullPath()); + : processor.getRegionDestroyedMembers(rc.internalRegion.getFullPath()); successfulRecipients.removeAll(cacheClosedMembers); successfulRecipients.removeAll(regionDestroyedMembers); try { - rc.r.handleReliableDistribution(successfulRecipients); + rc.internalRegion.handleReliableDistribution(successfulRecipients); } catch (RegionDistributionException e) { if (regionDistributionExceptions == Collections.emptySet()) { regionDistributionExceptions = new HashSet(); failedRegionNames = new HashSet(); } regionDistributionExceptions.add(e); - failedRegionNames.add(rc.r.getFullPath()); + failedRegionNames.add(rc.internalRegion.getFullPath()); } } @@ -576,14 +583,6 @@ public class TXCommitMessage extends PooledDistributionMessage this.dm = dm; } - public DistributionManager getDM() { - if (this.dm == null) { - InternalCache cache = GemFireCacheImpl.getExisting("Applying TXCommit"); - this.dm = cache.getDistributionManager(); - } - return this.dm; - } - public void basicProcess() { final DistributionManager dm = this.dm; @@ -630,7 +629,7 @@ public class TXCommitMessage extends PooledDistributionMessage processCacheRuntimeException(problem); } finally { if (failedBeginProcess) { - rc.r = null; // Cause related FarSideEntryOps to skip processing + rc.internalRegion = null; // Cause related FarSideEntryOps to skip processing it.remove(); // Skip endProcessing as well } } @@ -813,16 +812,17 @@ public class TXCommitMessage extends PooledDistributionMessage this.farsideBaseThreadId = in.readLong(); this.farsideBaseSequenceId = in.readLong(); - this.needsLargeModCount = in.readBoolean(); + final boolean hasShadowKeys = hasFlagsField(in) ? in.readBoolean() : useShadowKey(); + int regionsSize = in.readInt(); this.regions = new ArrayList(regionsSize); this.farSideEntryOps = new ArrayList(totalMaxSize); for (int i = 0; i < regionsSize; i++) { RegionCommit rc = new RegionCommit(this); try { - rc.fromData(in); + rc.fromData(in, hasShadowKeys); } catch (CacheClosedException cce) { addProcessingException(cce); // return to avoid serialization error being sent in reply @@ -898,13 +898,17 @@ public class TXCommitMessage extends PooledDistributionMessage DataSerializer.writeBoolean(this.needsLargeModCount, out); } + final boolean useShadowKey = useShadowKey(); + if (hasFlagsField(out)) { + out.writeBoolean(useShadowKey); + } out.writeInt(regionsSize); { if (regionsSize > 0) { for (int i = 0; i < this.regions.size(); i++) { RegionCommit rc = (RegionCommit) this.regions.get(i); - rc.toData(out); + rc.toData(out, useShadowKey); } } } @@ -914,6 +918,21 @@ public class TXCommitMessage extends PooledDistributionMessage DataSerializer.writeHashSet(this.farSiders, out); } + private boolean hasFlagsField(final DataOutput out) { + return hasFlagsField(InternalDataSerializer.getVersionForDataStream(out)); + } + + private boolean hasFlagsField(final DataInput in) { + return hasFlagsField(InternalDataSerializer.getVersionForDataStream(in)); + } + + private boolean hasFlagsField(final Version version) { + return version.compareTo(Version.GEODE_180) >= 0; + } + + private boolean useShadowKey() { + return null == clientVersion; + } @Override public String toString() { @@ -946,7 +965,8 @@ public class TXCommitMessage extends PooledDistributionMessage /** * Combines a set of small TXCommitMessages that belong to one transaction into a txCommitMessage * that represents an entire transaction. At commit time the txCommitMessage sent to each node can - * be a subset of the transaction, this method will combine those subsets into a complete message. + * be a subset of the transaction, this method will combine those subsets into a complete + * message. * * @return the complete txCommitMessage */ @@ -1052,7 +1072,7 @@ public class TXCommitMessage extends PooledDistributionMessage /** * The region that this commit represents. Valid on both nearside and farside. */ - protected transient InternalRegion r; + protected transient InternalRegion internalRegion; /** * Valid only on farside. */ @@ -1100,7 +1120,7 @@ public class TXCommitMessage extends PooledDistributionMessage */ RegionCommit(TXCommitMessage msg, InternalRegion r, int maxSize) { this.msg = msg; - this.r = r; + this.internalRegion = r; this.maxSize = maxSize; } @@ -1144,20 +1164,21 @@ public class TXCommitMessage extends PooledDistributionMessage if (!hookupRegion(dm)) { return false; } - if (msg.isAckRequired() && (this.r == null || !this.r.getScope().isDistributed())) { + if (msg.isAckRequired() + && (this.internalRegion == null || !this.internalRegion.getScope().isDistributed())) { if (logger.isDebugEnabled()) { logger.debug("Received unneeded commit data for region {}", this.regionPath); } this.msg.addProcessingException(new RegionDestroyedException( LocalizedStrings.TXCommitMessage_REGION_NOT_FOUND.toLocalizedString(), this.regionPath)); - this.r = null; + this.internalRegion = null; return false; } - this.needsUnlock = this.r.lockGII(); - this.r.txLRUStart(); + this.needsUnlock = this.internalRegion.lockGII(); + this.internalRegion.txLRUStart(); this.needsLRUEnd = true; - if (this.r.isInitialized()) { + if (this.internalRegion.isInitialized()) { // We don't want the txEvent to know anything about our regions // that are still doing gii. this.txEvent = txEvent; @@ -1170,18 +1191,18 @@ public class TXCommitMessage extends PooledDistributionMessage "Received unneeded commit data for region {} because the region was destroyed.", this.regionPath, e); } - this.r = null; + this.internalRegion = null; } - return this.r != null; + return this.internalRegion != null; } private boolean hookupRegion(DistributionManager dm) { - this.r = getRegionByPath(dm, regionPath); - if (this.r == null && this.parentRegionPath != null) { - this.r = getRegionByPath(dm, this.parentRegionPath); + this.internalRegion = getRegionByPath(dm, regionPath); + if (this.internalRegion == null && this.parentRegionPath != null) { + this.internalRegion = getRegionByPath(dm, this.parentRegionPath); this.regionPath = this.parentRegionPath; } - if (this.r == null && dm.getSystem().isLoner()) { + if (this.internalRegion == null && dm.getSystem().isLoner()) { // If there are additional regions that the server enlisted in the tx, // which the client does not have, the client can just ignore the region // see bug 51922 @@ -1199,16 +1220,16 @@ public class TXCommitMessage extends PooledDistributionMessage * Called when processing is complete; only needs to be called if beginProcess returned true. */ void endProcess() { - if (this.r != null) { + if (this.internalRegion != null) { try { if (this.needsLRUEnd) { this.needsLRUEnd = false; - this.r.txLRUEnd(); + this.internalRegion.txLRUEnd(); } } finally { if (this.needsUnlock) { this.needsUnlock = false; - this.r.unlockGII(); + this.internalRegion.unlockGII(); } } } @@ -1229,25 +1250,27 @@ public class TXCommitMessage extends PooledDistributionMessage */ @SuppressWarnings("synthetic-access") protected void txApplyEntryOp(FarSideEntryOp entryOp, List<EntryEventImpl> pendingCallbacks) { - if (this.r == null) { + if (this.internalRegion == null) { return; } EventID eventID = getEventId(entryOp); - boolean isDuplicate = this.r.hasSeenEvent(eventID); - boolean callbacksOnly = (this.r.getDataPolicy() == DataPolicy.PARTITION) || isDuplicate; - if (this.r instanceof PartitionedRegion) { + boolean isDuplicate = this.internalRegion.hasSeenEvent(eventID); + boolean callbacksOnly = + (this.internalRegion.getDataPolicy() == DataPolicy.PARTITION) || isDuplicate; + if (this.internalRegion instanceof PartitionedRegion) { /* * This happens when we don't have the bucket and are getting adjunct notification */ // No need to release because it is added to pendingCallbacks and they will be released // later - EntryEventImpl eei = AbstractRegionMap.createCallbackEvent(this.r, entryOp.op, entryOp.key, - entryOp.value, this.msg.txIdent, txEvent, getEventId(entryOp), entryOp.callbackArg, - entryOp.filterRoutingInfo, this.msg.bridgeContext, null, entryOp.versionTag, - entryOp.tailKey); + EntryEventImpl eei = + AbstractRegionMap.createCallbackEvent(this.internalRegion, entryOp.op, entryOp.key, + entryOp.value, this.msg.txIdent, txEvent, getEventId(entryOp), entryOp.callbackArg, + entryOp.filterRoutingInfo, this.msg.bridgeContext, null, entryOp.versionTag, + entryOp.tailKey); if (entryOp.filterRoutingInfo != null) { eei.setLocalFilterInfo( - entryOp.filterRoutingInfo.getFilterInfo(this.r.getCache().getMyId())); + entryOp.filterRoutingInfo.getFilterInfo(this.internalRegion.getCache().getMyId())); } if (isDuplicate) { eei.setPossibleDuplicate(true); @@ -1274,17 +1297,19 @@ public class TXCommitMessage extends PooledDistributionMessage entryOp.versionTag.replaceNullIDs(this.msg.getSender()); } if (entryOp.op.isDestroy()) { - this.r.txApplyDestroy(entryOp.key, this.msg.txIdent, this.txEvent, this.needsUnlock, + this.internalRegion.txApplyDestroy(entryOp.key, this.msg.txIdent, this.txEvent, + this.needsUnlock, entryOp.op, getEventId(entryOp), entryOp.callbackArg, pendingCallbacks, entryOp.filterRoutingInfo, this.msg.bridgeContext, false /* origin remote */, null/* txEntryState */, entryOp.versionTag, entryOp.tailKey); } else if (entryOp.op.isInvalidate()) { - this.r.txApplyInvalidate(entryOp.key, Token.INVALID, entryOp.didDestroy, this.msg.txIdent, + this.internalRegion.txApplyInvalidate(entryOp.key, Token.INVALID, entryOp.didDestroy, + this.msg.txIdent, this.txEvent, false /* localOp */, getEventId(entryOp), entryOp.callbackArg, pendingCallbacks, entryOp.filterRoutingInfo, this.msg.bridgeContext, null/* txEntryState */, entryOp.versionTag, entryOp.tailKey); } else { - this.r.txApplyPut(entryOp.op, entryOp.key, entryOp.value, entryOp.didDestroy, + this.internalRegion.txApplyPut(entryOp.op, entryOp.key, entryOp.value, entryOp.didDestroy, this.msg.txIdent, this.txEvent, getEventId(entryOp), entryOp.callbackArg, pendingCallbacks, entryOp.filterRoutingInfo, this.msg.bridgeContext, null/* txEntryState */, entryOp.versionTag, entryOp.tailKey); @@ -1296,18 +1321,19 @@ public class TXCommitMessage extends PooledDistributionMessage */ @SuppressWarnings("synthetic-access") protected void txApplyEntryOpAdjunctOnly(FarSideEntryOp entryOp) { - if (this.r == null) { + if (this.internalRegion == null) { return; } EventID eventID = getEventId(entryOp); - boolean isDuplicate = this.r.hasSeenEvent(eventID); - boolean callbacksOnly = (this.r.getDataPolicy() == DataPolicy.PARTITION) || isDuplicate; - if (this.r instanceof PartitionedRegion) { + boolean isDuplicate = this.internalRegion.hasSeenEvent(eventID); + boolean callbacksOnly = + (this.internalRegion.getDataPolicy() == DataPolicy.PARTITION) || isDuplicate; + if (this.internalRegion instanceof PartitionedRegion) { - PartitionedRegion pr = (PartitionedRegion) r; + PartitionedRegion pr = (PartitionedRegion) internalRegion; BucketRegion br = pr.getBucketRegion(entryOp.key); Set bucketOwners = br.getBucketOwners(); - InternalDistributedMember thisMember = this.r.getDistributionManager().getId(); + InternalDistributedMember thisMember = this.internalRegion.getDistributionManager().getId(); if (bucketOwners.contains(thisMember)) { return; } @@ -1316,14 +1342,15 @@ public class TXCommitMessage extends PooledDistributionMessage * This happens when we don't have the bucket and are getting adjunct notification */ @Released - EntryEventImpl eei = AbstractRegionMap.createCallbackEvent(this.r, entryOp.op, entryOp.key, - entryOp.value, this.msg.txIdent, txEvent, getEventId(entryOp), entryOp.callbackArg, - entryOp.filterRoutingInfo, this.msg.bridgeContext, null, entryOp.versionTag, - entryOp.tailKey); + EntryEventImpl eei = + AbstractRegionMap.createCallbackEvent(this.internalRegion, entryOp.op, entryOp.key, + entryOp.value, this.msg.txIdent, txEvent, getEventId(entryOp), entryOp.callbackArg, + entryOp.filterRoutingInfo, this.msg.bridgeContext, null, entryOp.versionTag, + entryOp.tailKey); try { if (entryOp.filterRoutingInfo != null) { eei.setLocalFilterInfo( - entryOp.filterRoutingInfo.getFilterInfo(this.r.getCache().getMyId())); + entryOp.filterRoutingInfo.getFilterInfo(this.internalRegion.getCache().getMyId())); } if (isDuplicate) { eei.setPossibleDuplicate(true); @@ -1337,7 +1364,7 @@ public class TXCommitMessage extends PooledDistributionMessage // the message was sent and already reflects the change caused by this event. // In the latter case we need to invoke listeners final boolean skipListeners = !isDuplicate; - eei.invokeCallbacks(this.r, skipListeners, true); + eei.invokeCallbacks(this.internalRegion, skipListeners, true); } finally { eei.release(); } @@ -1350,7 +1377,7 @@ public class TXCommitMessage extends PooledDistributionMessage } boolean needsAck() { - return this.r.getScope().isDistributedAck(); + return this.internalRegion.getScope().isDistributedAck(); } void addOp(Object key, TXEntryState entry) { @@ -1371,7 +1398,8 @@ public class TXCommitMessage extends PooledDistributionMessage return true; } - public void fromData(DataInput in) throws IOException, ClassNotFoundException { + public void fromData(DataInput in, boolean hasShadowKey) + throws IOException, ClassNotFoundException { this.regionPath = DataSerializer.readString(in); this.parentRegionPath = DataSerializer.readString(in); @@ -1384,7 +1412,7 @@ public class TXCommitMessage extends PooledDistributionMessage for (int i = 0; i < size; i++) { FarSideEntryOp entryOp = new FarSideEntryOp(); // shadowkey is not being sent to clients - entryOp.fromData(in, largeModCount, hasShadowKey(regionPath, parentRegionPath)); + entryOp.fromData(in, largeModCount, hasShadowKey); if (entryOp.versionTag != null && this.memberId != null) { entryOp.versionTag.setMemberID(this.memberId); } @@ -1395,27 +1423,13 @@ public class TXCommitMessage extends PooledDistributionMessage } } - private boolean hasShadowKey(String regionPath, String parentRegionPath) { - // in bucket region, regionPath is bucket name, use parentRegionPath - String path = parentRegionPath != null ? parentRegionPath : regionPath; - LocalRegion region = getRegionByPath(msg.getDM(), path); - - // default value is whether loner or not, region is null if destroyRegion executed - boolean readShadowKey = !msg.getDM().isLoner(); - if (region != null) { - // shadowkey is not being sent to clients - readShadowKey = region.getPoolName() == null; - } - return readShadowKey; - } - @Override public String toString() { StringBuilder result = new StringBuilder(64); if (this.regionPath != null) { result.append(this.regionPath); } else { - result.append(this.r.getFullPath()); + result.append(this.internalRegion.getFullPath()); } if (this.refCount > 0) { result.append(" refCount=").append(this.refCount); @@ -1423,11 +1437,12 @@ public class TXCommitMessage extends PooledDistributionMessage return result.toString(); } - private void basicToData(DataOutput out) throws IOException { - if (this.r != null) { - DataSerializer.writeString(this.r.getFullPath(), out); - if (this.r instanceof BucketRegion) { - DataSerializer.writeString(((Bucket) this.r).getPartitionedRegion().getFullPath(), out); + private void basicToData(DataOutput out, boolean useShadowKey) throws IOException { + if (this.internalRegion != null) { + DataSerializer.writeString(this.internalRegion.getFullPath(), out); + if (this.internalRegion instanceof BucketRegion) { + DataSerializer.writeString( + ((Bucket) this.internalRegion).getPartitionedRegion().getFullPath(), out); } else { DataSerializer.writeString(null, out); } @@ -1455,10 +1470,10 @@ public class TXCommitMessage extends PooledDistributionMessage if (sendVersionTags) { VersionSource member = this.memberId; if (member == null) { - if (this.r == null) { + if (this.internalRegion == null) { Assert.assertTrue(this.msg.txState == null); } else { - member = this.r.getVersionMember(); + member = this.internalRegion.getVersionMember(); } } DataSerializer.writeObject(member, out); @@ -1468,28 +1483,28 @@ public class TXCommitMessage extends PooledDistributionMessage if (this.msg.txState != null) { /* we are still on tx node and have the entry state */ ((TXEntryState) this.opEntries.get(i)).toFarSideData(out, largeModCount, - sendVersionTags, this.msg.clientVersion == null); + sendVersionTags, useShadowKey); } else { ((FarSideEntryOp) this.opEntries.get(i)).toData(out, largeModCount, sendVersionTags, - this.msg.clientVersion == null); + useShadowKey); } } } } - public void toData(DataOutput out) throws IOException { + public void toData(DataOutput out, boolean useShadowKey) throws IOException { if (this.preserializedBuffer != null) { this.preserializedBuffer.rewind(); this.preserializedBuffer.sendTo(out); } else if (this.refCount > 1) { Version v = InternalDataSerializer.getVersionForDataStream(out); HeapDataOutputStream hdos = new HeapDataOutputStream(1024, v); - basicToData(hdos); + basicToData(hdos, useShadowKey); this.preserializedBuffer = hdos; this.preserializedBuffer.sendTo(out); } else { - basicToData(out); + basicToData(out, useShadowKey); } } @@ -1621,8 +1636,9 @@ public class TXCommitMessage extends PooledDistributionMessage @Override public boolean equals(Object o) { - if (o == null || !(o instanceof FarSideEntryOp)) + if (o == null || !(o instanceof FarSideEntryOp)) { return false; + } return compareTo(o) == 0; } @@ -1941,9 +1957,12 @@ public class TXCommitMessage extends PooledDistributionMessage @Override public void quorumLost(DistributionManager distributionManager, - Set<InternalDistributedMember> failures, List<InternalDistributedMember> remaining) {} + Set<InternalDistributedMember> failures, + List<InternalDistributedMember> remaining) {} - /** return true if the member initiating this transaction has left the cluster */ + /** + * return true if the member initiating this transaction has left the cluster + */ public boolean isDepartureNoticed() { return departureNoticed; } @@ -2172,11 +2191,17 @@ public class TXCommitMessage extends PooledDistributionMessage */ public static class CommitExceptionCollectingException extends ReplyException { private static final long serialVersionUID = 589384721273797822L; - /** Set of members that threw CacheClosedExceptions */ + /** + * Set of members that threw CacheClosedExceptions + */ private final Set<InternalDistributedMember> cacheExceptions; - /** key=region path, value=Set of members */ + /** + * key=region path, value=Set of members + */ private final Map<String, Set<InternalDistributedMember>> regionExceptions; - /** List of exceptions that were unexpected and caused the tx to fail */ + /** + * List of exceptions that were unexpected and caused the tx to fail + */ private final Map fatalExceptions; private final TXId id; @@ -2236,7 +2261,7 @@ public class TXCommitMessage extends PooledDistributionMessage RegionCommitList rcl = memberMap.getValue(); for (RegionCommit region : rcl) { Set<InternalDistributedMember> failedMembers = - regionExceptions.get(region.r.getFullPath()); + regionExceptions.get(region.internalRegion.getFullPath()); if (failedMembers != null && failedMembers.contains(member)) { markMemberOffline(member, region); } @@ -2275,11 +2300,12 @@ public class TXCommitMessage extends PooledDistributionMessage // if we have started to shutdown, we don't want to mark the peer // as offline, or we will think we have newer data when in fact we don't - region.r.getCancelCriterion().checkCancelInProgress(null); + region.internalRegion.getCancelCriterion().checkCancelInProgress(null); // Otherwise, mark the peer as offline, because it didn't complete // the operation. - ((DistributedRegion) region.r).getPersistenceAdvisor().markMemberOffline(member, + ((DistributedRegion) region.internalRegion).getPersistenceAdvisor().markMemberOffline( + member, persistentId); } } diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/TXRegionState.java b/geode-core/src/main/java/org/apache/geode/internal/cache/TXRegionState.java index fc5bf1f..a061b34 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/TXRegionState.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/TXRegionState.java @@ -73,10 +73,6 @@ public class TXRegionState { LocalizedStrings.TXRegionState_OPERATIONS_ON_GLOBAL_REGIONS_ARE_NOT_ALLOWED_BECAUSE_THIS_THREAD_HAS_AN_ACTIVE_TRANSACTION .toLocalizedString()); } - if (r.hasServerProxy()) { - // throw new - // UnsupportedOperationException(LocalizedStrings.TXRegionState_OPERATIONS_ON_REGION_WITH_CLIENT_POOL_ARE_NOT_ALLOWED_BECAUSE_THIS_THREAD_HAS_AN_ACTIVE_TRANSACTION.toLocalizedString()); - } this.entryMods = new HashMap<Object, TXEntryState>(); this.uaMods = null; this.region = r; diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/TxCommitMessageTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/TxCommitMessageTest.java new file mode 100755 index 0000000..489b895 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/TxCommitMessageTest.java @@ -0,0 +1,1167 @@ +/* + * 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.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.Sequence; +import org.jmock.lib.concurrent.Synchroniser; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.cache.Scope; +import org.apache.geode.distributed.internal.DistributionManager; +import org.apache.geode.distributed.internal.membership.InternalDistributedMember; +import org.apache.geode.internal.Version; +import org.apache.geode.internal.VersionedDataStream; +import org.apache.geode.internal.cache.versions.VersionSource; +import org.apache.geode.test.junit.categories.UnitTest; + +/** + * Unit tests for TxCommitMessage. + */ +@Category(UnitTest.class) +public class TxCommitMessageTest { + + private Mockery mockContext; + + @Before + public void setUp() { + mockContext = new Mockery() { + { + setImposteriser(ClassImposteriser.INSTANCE); + setThreadingPolicy(new Synchroniser()); + } + }; + } + + @After + public void tearDown() { + mockContext.assertIsSatisfied(); + mockContext = null; + } + + public interface VersionedDataOutput extends DataOutput, VersionedDataStream { + + } + + public interface VersionedDataInput extends DataInput, VersionedDataStream { + + } + + @Test + public void toDataWithShadowKeyPre180Server() throws IOException { + final Sequence toData = mockContext.sequence("toData"); + final VersionedDataOutput mockDataOutput = mockContext.mock(VersionedDataOutput.class); + mockContext.checking(new Expectations() { + { + allowing(mockDataOutput).getVersion(); + will(returnValue(Version.GEODE_170)); + // processor id + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + // txId.uniqId + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // lockId + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // totalMaxSize + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // txState.membershipId + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + // txState.baseThreadId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.baseSequenceId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // regionsSize + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + + // regionPath: "/r" + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(2); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("/r"); + inSequence(toData); + // parentRegionPath: null string + oneOf(mockDataOutput).writeByte(69); + inSequence(toData); + // opKeys size + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + // needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // versionMember + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + // opKeys[0] + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(3); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("key"); + inSequence(toData); + // farSideData[0] + oneOf(mockDataOutput).writeByte(17); + inSequence(toData); + oneOf(mockDataOutput).writeByte(0); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // shadowkey + oneOf(mockDataOutput).writeLong(-1L); + inSequence(toData); + // offset + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + + // bridgeContext + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // farSiders + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + } + }); + + final InternalDistributedMember mockInternalDistributedMember = + createInternalDistributedMember(); + + final TXId txId = new TXId(mockInternalDistributedMember, 0); + final TXState txState = new TXState(null, false); + final TXCommitMessage txCommitMessage = new TXCommitMessage(txId, null, txState); + + final InternalRegion mockInternalRegion = + createMockInternalRegion(mockInternalDistributedMember); + txCommitMessage.startRegion(mockInternalRegion, 0); + final EntryEventImpl mockEntryEventImpl = createMockEntryEvent(mockInternalRegion); + final TXEntryState txEntryState = createTxEntryState(mockInternalRegion, mockEntryEventImpl); + txCommitMessage.addOp(null, "key", txEntryState, null); + txCommitMessage.finishRegionComplete(); + + txCommitMessage.toData(mockDataOutput); + } + + @Test + public void toDataWithoutShadowKeyPre180Client() throws IOException { + final Sequence toData = mockContext.sequence("toData"); + final VersionedDataOutput mockDataOutput = mockContext.mock(VersionedDataOutput.class); + mockContext.checking(new Expectations() { + { + allowing(mockDataOutput).getVersion(); + will(returnValue(Version.GEODE_170)); + // processor id + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + // txId.uniqId + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // lockId + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // totalMaxSize + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // txState.membershipId + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + // txState.baseThreadId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.baseSequenceId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // regionsSize + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + + // regionPath: "/r" + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(2); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("/r"); + inSequence(toData); + // parentRegionPath: null string + oneOf(mockDataOutput).writeByte(69); + inSequence(toData); + // opKeys size + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + // needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // versionMember + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + // opKeys[0] + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(3); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("key"); + inSequence(toData); + // farSideData[0] + oneOf(mockDataOutput).writeByte(17); + inSequence(toData); + oneOf(mockDataOutput).writeByte(0); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // no shadowkey + // offset + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + + // bridgeContext + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // farSiders + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + } + }); + + final InternalDistributedMember mockInternalDistributedMember = + createInternalDistributedMember(); + + final TXId txId = new TXId(mockInternalDistributedMember, 0); + final TXState txState = new TXState(null, false); + final TXCommitMessage txCommitMessage = new TXCommitMessage(txId, null, txState); + txCommitMessage.setClientVersion(Version.GEODE_170); + + final InternalRegion mockInternalRegion = + createMockInternalRegion(mockInternalDistributedMember); + txCommitMessage.startRegion(mockInternalRegion, 0); + final EntryEventImpl mockEntryEventImpl = createMockEntryEvent(mockInternalRegion); + final TXEntryState txEntryState = createTxEntryState(mockInternalRegion, mockEntryEventImpl); + txCommitMessage.addOp(null, "key", txEntryState, null); + txCommitMessage.finishRegionComplete(); + + txCommitMessage.toData(mockDataOutput); + } + + @Test + public void toDataWithShadowKeyPost180Server() throws IOException { + final Sequence toData = mockContext.sequence("toData"); + final VersionedDataOutput mockDataOutput = mockContext.mock(VersionedDataOutput.class); + mockContext.checking(new Expectations() { + { + allowing(mockDataOutput).getVersion(); + will(returnValue(Version.CURRENT)); + // processor id + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + // txId.uniqId + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // lockId + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // totalMaxSize + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // txState.membershipId + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + // txState.baseThreadId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.baseSequenceId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // hasShadowKeys + oneOf(mockDataOutput).writeBoolean(true); + inSequence(toData); + // regionsSize + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + + // regionPath: "/r" + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(2); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("/r"); + inSequence(toData); + // parentRegionPath: null string + oneOf(mockDataOutput).writeByte(69); + inSequence(toData); + // opKeys size + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + // needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // versionMember + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + // opKeys[0] + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(3); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("key"); + inSequence(toData); + // farSideData[0] + oneOf(mockDataOutput).writeByte(17); + inSequence(toData); + oneOf(mockDataOutput).writeByte(0); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // shadowkey + oneOf(mockDataOutput).writeLong(-1L); + inSequence(toData); + // offset + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + + // bridgeContext + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // farSiders + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + } + }); + + final InternalDistributedMember mockInternalDistributedMember = + createInternalDistributedMember(); + + final TXId txId = new TXId(mockInternalDistributedMember, 0); + final TXState txState = new TXState(null, false); + final TXCommitMessage txCommitMessage = new TXCommitMessage(txId, null, txState); + + final InternalRegion mockInternalRegion = + createMockInternalRegion(mockInternalDistributedMember); + txCommitMessage.startRegion(mockInternalRegion, 0); + final EntryEventImpl mockEntryEventImpl = createMockEntryEvent(mockInternalRegion); + final TXEntryState txEntryState = createTxEntryState(mockInternalRegion, mockEntryEventImpl); + txCommitMessage.addOp(null, "key", txEntryState, null); + txCommitMessage.finishRegionComplete(); + + txCommitMessage.toData(mockDataOutput); + } + + @Test + public void toDataWithoutShadowKeyPost180Client() throws IOException { + final Sequence toData = mockContext.sequence("toData"); + final VersionedDataOutput mockDataOutput = mockContext.mock(VersionedDataOutput.class); + mockContext.checking(new Expectations() { + { + allowing(mockDataOutput).getVersion(); + will(returnValue(Version.CURRENT)); + // processor id + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + // txId.uniqId + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // lockId + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // totalMaxSize + oneOf(mockDataOutput).writeInt(0); + inSequence(toData); + // txState.membershipId + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + // txState.baseThreadId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.baseSequenceId + oneOf(mockDataOutput).writeLong(with(any(long.class))); + inSequence(toData); + // txState.needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // hasShadowKeys + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // regionsSize + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + + // regionPath: "/r" + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(2); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("/r"); + inSequence(toData); + // parentRegionPath: null string + oneOf(mockDataOutput).writeByte(69); + inSequence(toData); + // opKeys size + oneOf(mockDataOutput).writeInt(1); + inSequence(toData); + // needsLargeModCount + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + // versionMember + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + oneOf(mockDataOutput).writeByte(1); + inSequence(toData); + // opKeys[0] + oneOf(mockDataOutput).writeByte(87); + inSequence(toData); + oneOf(mockDataOutput).writeShort(3); + inSequence(toData); + oneOf(mockDataOutput).writeBytes("key"); + inSequence(toData); + // farSideData[0] + oneOf(mockDataOutput).writeByte(17); + inSequence(toData); + oneOf(mockDataOutput).writeByte(0); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // no shadowkey + // offset + oneOf(mockDataOutput).writeInt(with(any(int.class))); + inSequence(toData); + oneOf(mockDataOutput).writeBoolean(false); + inSequence(toData); + + // bridgeContext + oneOf(mockDataOutput).writeByte(41); + inSequence(toData); + // farSiders + oneOf(mockDataOutput).writeByte(-1); + inSequence(toData); + } + }); + + final InternalDistributedMember mockInternalDistributedMember = + createInternalDistributedMember(); + + final TXId txId = new TXId(mockInternalDistributedMember, 0); + final TXState txState = new TXState(null, false); + final TXCommitMessage txCommitMessage = new TXCommitMessage(txId, null, txState); + txCommitMessage.setClientVersion(Version.CURRENT); + + final InternalRegion mockInternalRegion = + createMockInternalRegion(mockInternalDistributedMember); + txCommitMessage.startRegion(mockInternalRegion, 0); + final EntryEventImpl mockEntryEventImpl = createMockEntryEvent(mockInternalRegion); + final TXEntryState txEntryState = createTxEntryState(mockInternalRegion, mockEntryEventImpl); + txCommitMessage.addOp(null, "key", txEntryState, null); + txCommitMessage.finishRegionComplete(); + + txCommitMessage.toData(mockDataOutput); + } + + @Test + public void fromDataWithShadowKeyPre180Server() throws Exception { + final Sequence fromData = mockContext.sequence("fromData"); + final VersionedDataInput mockDataInput = mockContext.mock(VersionedDataInput.class); + mockContext.checking(new Expectations() { + { + allowing(mockDataInput).getVersion(); + will(returnValue(Version.GEODE_170)); + // processor id + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // txId.uniqId + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // member version + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedByte(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedByte(); + will(returnValue(1)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + // durableId + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 0)); + inSequence(fromData); + + // lockId + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + // totalMaxSize + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // txState.membershipId + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + // txState.baseThreadId + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + // txState.baseSequenceId + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + // txState.needsLargeModCount + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // regionsSize + oneOf(mockDataInput).readInt(); + will(returnValue(1)); + inSequence(fromData); + + // regionPath: "/r" + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(2)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + // opKeys size + oneOf(mockDataInput).readInt(); + will(returnValue(1)); + inSequence(fromData); + // needsLargeModCount + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + // versionMember + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + + // opKeys[0] + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(3)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + // farSideData[0] + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 17)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 0)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + // shadowkey + oneOf(mockDataInput).readLong(); + will(returnValue(-1L)); + inSequence(fromData); + // offset + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // bridgeContext + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + // farSiders + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + } + }); + + final DistributionManager mockDistributionManager = + mockContext.mock(DistributionManager.class); + mockContext.checking(new Expectations() { + { + allowing(mockDistributionManager).getCache(); + will(returnValue(null)); + allowing(mockDistributionManager).isLoner(); + will(returnValue(false)); + } + }); + + final TXCommitMessage txCommitMessage = new TXCommitMessage(); + txCommitMessage.setDM(mockDistributionManager); + txCommitMessage.fromData(mockDataInput); + } + + @Test + public void fromDataWithShadowKeyPost180Server() throws Exception { + final Sequence fromData = mockContext.sequence("fromData"); + final DataInput mockDataInput = mockContext.mock(DataInput.class); + mockContext.checking(new Expectations() { + { + // processor id + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // txId.uniqId + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // member version + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedByte(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedByte(); + will(returnValue(1)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + // durableId + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 0)); + inSequence(fromData); + + // lockId + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + // totalMaxSize + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // txState.membershipId + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + // txState.baseThreadId + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + // txState.baseSequenceId + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + // txState.needsLargeModCount + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // hasShadowKeys + oneOf(mockDataInput).readBoolean(); + will(returnValue(true)); + inSequence(fromData); + + // regionsSize + oneOf(mockDataInput).readInt(); + will(returnValue(1)); + inSequence(fromData); + + // regionPath: "/r" + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(2)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + // opKeys size + oneOf(mockDataInput).readInt(); + will(returnValue(1)); + inSequence(fromData); + // needsLargeModCount + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + // versionMember + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + + // opKeys[0] + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(3)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + // farSideData[0] + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 17)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 0)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + // shadowkey + oneOf(mockDataInput).readLong(); + will(returnValue(-1L)); + inSequence(fromData); + // offset + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // bridgeContext + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + // farSiders + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + } + }); + + final DistributionManager mockDistributionManager = + mockContext.mock(DistributionManager.class); + mockContext.checking(new Expectations() { + { + allowing(mockDistributionManager).getCache(); + will(returnValue(null)); + allowing(mockDistributionManager).isLoner(); + will(returnValue(false)); + } + }); + + final TXCommitMessage txCommitMessage = new TXCommitMessage(); + txCommitMessage.setDM(mockDistributionManager); + txCommitMessage.fromData(mockDataInput); + } + + @Test + public void fromDataWithoutShadowKeyPost180Client() throws Exception { + final Sequence fromData = mockContext.sequence("fromData"); + final DataInput mockDataInput = mockContext.mock(DataInput.class); + mockContext.checking(new Expectations() { + { + // processor id + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // txId.uniqId + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // member version + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedByte(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedByte(); + will(returnValue(1)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + // durableId + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 0)); + inSequence(fromData); + + // lockId + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + // totalMaxSize + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + // txState.membershipId + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + // txState.baseThreadId + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + // txState.baseSequenceId + oneOf(mockDataInput).readLong(); + will(returnValue(0L)); + inSequence(fromData); + // txState.needsLargeModCount + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // hasShadowKeys + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // regionsSize + oneOf(mockDataInput).readInt(); + will(returnValue(1)); + inSequence(fromData); + + // regionPath: "/r" + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(2)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 69)); + inSequence(fromData); + // opKeys size + oneOf(mockDataInput).readInt(); + will(returnValue(1)); + inSequence(fromData); + // needsLargeModCount + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + // versionMember + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + + // opKeys[0] + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 87)); + inSequence(fromData); + oneOf(mockDataInput).readUnsignedShort(); + will(returnValue(3)); + inSequence(fromData); + oneOf(mockDataInput) + .readFully(with(any(byte[].class)), with(any(int.class)), with(any(int.class))); + inSequence(fromData); + // farSideData[0] + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 17)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 0)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + // no shadowkey + // offset + oneOf(mockDataInput).readInt(); + will(returnValue(0)); + inSequence(fromData); + oneOf(mockDataInput).readBoolean(); + will(returnValue(false)); + inSequence(fromData); + + // bridgeContext + oneOf(mockDataInput).readByte(); + will(returnValue((byte) 41)); + inSequence(fromData); + // farSiders + oneOf(mockDataInput).readByte(); + will(returnValue((byte) -1)); + inSequence(fromData); + } + }); + + final DistributionManager mockDistributionManager = + mockContext.mock(DistributionManager.class); + mockContext.checking(new Expectations() { + { + allowing(mockDistributionManager).getCache(); + will(returnValue(null)); + allowing(mockDistributionManager).isLoner(); + will(returnValue(true)); + } + }); + + final TXCommitMessage txCommitMessage = new TXCommitMessage(); + txCommitMessage.setDM(mockDistributionManager); + txCommitMessage.fromData(mockDataInput); + } + + private InternalDistributedMember createInternalDistributedMember() throws IOException { + final InternalDistributedMember mockInternalDistributedMember = + mockContext.mock(InternalDistributedMember.class); + mockContext.checking(new Expectations() { + { + allowing(mockInternalDistributedMember).getDSFID(); + will(returnValue(1)); + allowing(mockInternalDistributedMember).toData(with(any(DataOutput.class))); + allowing(mockInternalDistributedMember).getSerializationVersions(); + will(returnValue(null)); + } + }); + return mockInternalDistributedMember; + } + + private EntryEventImpl createMockEntryEvent(InternalRegion mockInternalRegion) { + final EntryEventImpl mockEntryEventImpl = mockContext.mock(EntryEventImpl.class); + mockContext.checking(new Expectations() { + { + allowing(mockEntryEventImpl).isLocalInvalid(); + will(returnValue(false)); + allowing(mockEntryEventImpl).getRegion(); + will(returnValue(mockInternalRegion)); + ignoring(mockEntryEventImpl).putValueTXEntry(with(any(TXEntryState.class))); + ignoring(mockEntryEventImpl) + .setTXEntryOldValue(with(any(Object.class)), with(any(boolean.class))); + } + }); + return mockEntryEventImpl; + } + + private TXEntryState createTxEntryState(InternalRegion mockInternalRegion, + EntryEventImpl mockEntryEventImpl) { + final TXState txState = new TXState(null, false); + final TXRegionState txRegionState = new TXRegionState(mockInternalRegion, txState); + final TXEntryState txEntryState = + TXEntryState.getFactory().createEntry(null, null, null, null, txRegionState, false); + txEntryState.invalidate(mockEntryEventImpl); + txEntryState.generateEventOffsets(txState); + return txEntryState; + } + + private InternalRegion createMockInternalRegion(VersionSource mockVersionSource) { + final InternalRegion mockInternalRegion = mockContext.mock(InternalRegion.class); + mockContext.checking(new Expectations() { + { + allowing(mockInternalRegion).requiresReliabilityCheck(); + will(returnValue(false)); + allowing(mockInternalRegion).getVersionMember(); + will(returnValue(mockVersionSource)); + allowing(mockInternalRegion).getFullPath(); + will(returnValue("/r")); + allowing(mockInternalRegion).getPersistBackup(); + will(returnValue(false)); + allowing(mockInternalRegion).getScope(); + will(returnValue(Scope.LOCAL)); + allowing(mockInternalRegion).isEntryEvictionPossible(); + will(returnValue(false)); + allowing(mockInternalRegion).isEntryExpiryPossible(); + will(returnValue(false)); + ignoring(mockInternalRegion).setInUseByTransaction(true); + allowing(mockInternalRegion).getConcurrencyChecksEnabled(); + will(returnValue(false)); + } + }); + return mockInternalRegion; + } + +} diff --git a/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt index 33e476c..0975d5a 100644 --- a/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt +++ b/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt @@ -1311,8 +1311,8 @@ fromData,20 toData,9 org/apache/geode/internal/cache/TXCommitMessage,2 -fromData,211 -toData,292 +fromData,236 +toData,316 org/apache/geode/internal/cache/TXCommitMessage$CommitProcessForLockIdMessage,2 fromData,26 @@ -1331,8 +1331,8 @@ fromData,16 toData,16 org/apache/geode/internal/cache/TXCommitMessage$RegionCommit,2 -fromData,173 -toData,77 +fromData,164 +toData,82 org/apache/geode/internal/cache/TXCommitMessage$RegionCommit$FarSideEntryOp,2 fromData,171 -- To stop receiving notification emails like this one, please contact jbarr...@apache.org.