com.gemstone.gemfire.internal.cache.CacheDistributionAdvisor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
The newest version!
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.internal.cache;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.cache.CacheEvent;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.InterestPolicy;
import com.gemstone.gemfire.cache.RegionDestroyedException;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
import com.gemstone.gemfire.distributed.Role;
import com.gemstone.gemfire.distributed.internal.DistributionAdvisee;
import com.gemstone.gemfire.distributed.internal.DistributionAdvisor;
import com.gemstone.gemfire.distributed.internal.DistributionManager;
import com.gemstone.gemfire.distributed.internal.MembershipListener;
import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.Assert;
import com.gemstone.gemfire.internal.DSCODE;
import com.gemstone.gemfire.internal.InternalDataSerializer;
import com.gemstone.gemfire.internal.cache.partitioned.PRLocallyDestroyedException;
import com.gemstone.gemfire.internal.cache.persistence.DiskStoreID;
import com.gemstone.gemfire.internal.cache.persistence.PersistentMemberID;
import com.gemstone.gnu.trove.THashMap;
/**
* Adds bookkeeping info and cache-specific behavior to DistributionAdvisor.
* Adds bit-encoded flags in addition to object info.
* @author Eric Zoerner
*
*/
public class CacheDistributionAdvisor extends DistributionAdvisor {
// moved ROLLOVER_* constants to DistributionAdvisor
/** bit masks */
private static final int INTEREST_MASK = 0x01;
private static final int REPLICATE_MASK = 0x02;
private static final int LOADER_MASK = 0x04;
private static final int WRITER_MASK = 0x08;
private static final int LISTENER_MASK = 0x10;
private static final int DIST_ACK_MASK = 0x20;
private static final int GLOBAL_MASK = 0x40;
private static final int IN_RECOVERY_MASK = 0x80;
private static final int PERSISTENT_MASK = 0x100;
private static final int PROXY_MASK = 0x200;
private static final int PRELOADED_MASK = 0x400;
private static final int IS_PARTITIONED_MASK = 0x800;
private static final int REGION_INITIALIZED_MASK = 0x1000;
private static final int IS_GATEWAY_ENABLED_MASK = 0x2000;
//provider is no longer a supported attribute.
// private static final int IS_GII_PROVIDER_MASK = 0x4000;
private static final int PERSISTENT_ID_MASK = 0x4000;
/** does this member require operation notification (PartitionedRegions) */
protected static final int REQUIRES_NOTIFICATION_MASK = 0x8000;
private static final int HAS_CACHE_SERVER_MASK = 0x10000;
private static final int REQUIRES_OLD_VALUE_MASK = 0x20000;
private static final int MEMBER_UNINITIALIZED_MASK = 0x40000;
private static final int PERSISTENCE_INITIALIZED_MASK = 0x80000;
private static final int GATEWAY_SENDER_IDS_MASK = 0x100000;
private static final int ASYNC_EVENT_QUEUE_IDS_MASK = 0x200000;
private static final int HAS_ACTIVE_GATEWAY_SENDER_MASK = 0x400000;
private static final int HAS_ACTIVE_ASYNC_QUEUE_MASK = 0x800000;
private static final int IS_OFF_HEAP_MASK = 0x2000000;
private static final int HAS_DB_SYNCH_OR_ASYNC_LISTENER_MASK = 0x4000000;
// moved initializ* to DistributionAdvisor
// moved membershipVersion to DistributionAdvisor
// moved previousVersionOpCount to DistributionAdvisor
// moved currentVersionOpCount to DistributionAdvisor
// moved removedProfiles to DistributionAdvisor
/** Creates a new instance of CacheDistributionAdvisor */
protected CacheDistributionAdvisor(CacheDistributionAdvisee region) {
super(region);
}
public static CacheDistributionAdvisor createCacheDistributionAdvisor(CacheDistributionAdvisee region) {
CacheDistributionAdvisor advisor = new CacheDistributionAdvisor(region);
advisor.initialize();
return advisor;
}
@Override
public String toString() {
return "CacheDistributionAdvisor for region " + getAdvisee().getFullPath();
}
// moved toStringWithProfiles to DistributionAdvisor
// moved initializationGate to DistributionAdvisor
// moved isInitialized to DistributionAdvisor
// moved addMembershipListenerAndAdviseGeneric to DistributionAdvisor
@Override
protected synchronized boolean basicAddProfile(Profile p) {
boolean added = super.basicAddProfile(p);
DistributionAdvisee advisee = getAdvisee();
if (advisee instanceof LocalRegion) {
final Profile[] newProfiles = this.profiles;
((LocalRegion)advisee).profileAdded(this, p, newProfiles);
}
return added;
}
@Override
protected synchronized Profile basicRemoveMemberId(ProfileId id) {
Profile removed = super.basicRemoveMemberId(id);
if (removed != null) {
DistributionAdvisee advisee = getAdvisee();
if (advisee instanceof LocalRegion) {
final Profile[] remainingProfiles = this.profiles;
((LocalRegion)advisee).profileRemoved(this, removed, remainingProfiles);
}
}
return removed;
}
/**
* Returns a the set of members that either want all events or are caching data.
* @param excludeInRecovery if true then members in recovery are excluded
*/
private Set adviseAllEventsOrCached(final boolean excludeInRecovery) throws IllegalStateException {
getAdvisee().getCancelCriterion().checkCancelInProgress(null);
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (excludeInRecovery && cp.inRecovery) {
return false;
}
return cp.cachedOrAllEventsWithListener();
}
});
}
/**
* Provide recipient information for an update or create operation.
*/
final Set adviseUpdate(final EntryEventImpl event)
throws IllegalStateException {
if (event.hasNewValue() || event.getOperation().isPutAll()) {
// only need to distribute it to guys that want all events or cache data
return adviseAllEventsOrCached(true/*fixes 41147*/);
}
else {
return adviseCreateNullValue();
}
}
final Set adviseCreateNullValue() {
{
// The new value is null so this is a create with a null value,
// in which case we only need to distribute this message to replicates
// or all events that are not a proxy or if a proxy has a listener
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
DataPolicy dp = cp.dataPolicy;
return dp.withReplication() ||
(cp.allEvents() && (dp.withStorage() || cp.hasCacheListener));
}
});
}
}
/**
* Provide recipient information for netLoad
* @return Set of Serializable members that have a CacheLoader installed;
* no reference to Set kept by advisor so caller is free to modify it
*/
public Set adviseNetLoad() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile prof = (CacheProfile)profile;
// if region in cache is not yet initialized, exclude
if (!prof.regionInitialized // fix for bug 41102
|| prof.memberUnInitialized) {
return false;
}
return prof.hasCacheLoader;
}
});
}
public FilterRoutingInfo adviseFilterRouting(CacheEvent event, Set cacheOpRecipients){
FilterProfile fp = ((LocalRegion)event.getRegion()).getFilterProfile();
if (fp != null) {
return fp.getFilterRoutingInfoPart1(event, this.profiles, cacheOpRecipients);
}
return null;
}
/**
* Same as adviseGeneric except in recovery excluded.
*/
public Set adviseCacheOp() {
return adviseAllEventsOrCached(true);
}
/**
* Same as adviseCacheOp but only includes members that are playing the
* specified role.
* @since 5.0
*/
public Set adviseCacheOpRole(final Role role) {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
// if region in cache is not yet initialized, exclude
if (!cp.regionInitialized) {
return false;
}
// if member is not yet initialized, exclude
if (cp.memberUnInitialized) {
return false;
}
if (!cp.cachedOrAllEventsWithListener()) {
return false;
}
return cp.getDistributedMember().getRoles().contains(role);
}
});
}
/* *
* Same as adviseGeneric but excludes guys in recover
*/
public Set adviseInvalidateRegion() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
return !cp.inRecovery;
}
});
}
/** Same as adviseGeneric
*/
public Set adviseDestroyRegion() {
return adviseGeneric();
}
/**
* Provide recipient information for netWrite
* @return Set of Serializable member ids that have a CacheWriter installed;
* no reference to Set kept by advisor so caller is free to modify it
*/
public Set adviseNetWrite() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile prof = (CacheProfile)profile;
// if region in cache is in recovery, exclude
if (prof.inRecovery) {
return false;
}
return prof.hasCacheWriter;
}
});
}
public Set adviseInitializedReplicates() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy.withReplication() && cp.regionInitialized
&& !cp.memberUnInitialized) {
return true;
}
return false;
}
});
}
private static final ProfileVisitor hasUninitializedReplicateVisitor =
new ProfileVisitor() {
@Override
public boolean visit(DistributionAdvisor advisor, Profile profile,
int profileIndex, int numProfiles, Void aggregate) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy.withReplication() && !cp.regionInitialized) {
// break the visit since we found an uninitialized replica
return false;
}
return true;
}
};
public boolean hasUninitializedReplicate() {
return !accept(hasUninitializedReplicateVisitor, null);
}
/**
* Provide recipient information for netSearch
* @return Set of Serializable member ids that have the region and
* are have storage (no need to search an empty cache)
*/
public Set adviseNetSearch() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
// if region in cache is not yet initialized, exclude
if (!cp.regionInitialized) {
return false;
}
// if member is not yet initialized, exclude
if (cp.memberUnInitialized) {
return false;
}
DataPolicy dp = cp.dataPolicy;
return dp.withStorage();
}
});
}
// moved dumpProfiles to DistributionAdvisor
@SuppressWarnings("synthetic-access")
public InitialImageAdvice adviseInitialImage(InitialImageAdvice previousAdvice) {
LogWriterI18n log = getLogWriter();
initializationGate();
if (VERBOSE) {
dumpProfiles(log, "AdviseInitialImage");
}
//log.warning("adviseInitialImage", new Exception("stack trace"));
Profile[] allProfiles = this.profiles; // volatile read
if (allProfiles.length == 0) {
return new InitialImageAdvice(Collections.EMPTY_SET,
Collections.EMPTY_SET,
Collections.EMPTY_SET,
Collections.EMPTY_SET,
Collections.EMPTY_SET,
Collections.emptyMap());
}
Set replicates = new HashSet();
Set others = new HashSet();
Set preloaded = new HashSet();
Set empties = new HashSet();
Set uninitialized = new HashSet();
THashMap memberProfiles = new THashMap();
for (int i = 0; i < allProfiles.length; i++) {
CacheProfile profile = (CacheProfile)allProfiles[i];
//Make sure that we don't return a member that was in the previous initial image advice.
//Unless that member has changed it's profile since the last time we checked.
if(previousAdvice != null) {
CacheProfile previousProfile = previousAdvice.memberProfiles.get(profile.getDistributedMember());
if (previousProfile != null
&& previousProfile.getSerialNumber() == profile.getSerialNumber()
&& previousProfile.getVersion() == profile.getVersion()) {
continue;
}
}
// if region in cache is in recovery, exclude
if (profile.inRecovery) {
uninitialized.add(profile.getDistributedMember());
continue;
}
// No need to do a GII from uninitialized member.
if(!profile.regionInitialized) {
uninitialized.add(profile.getDistributedMember());
continue;
}
if (profile.dataPolicy.withReplication()) {
replicates.add(profile.getDistributedMember());
memberProfiles.put(profile.getDistributedMember(), profile);
}
else
if (profile.dataPolicy == DataPolicy.PRELOADED) {
preloaded.add(profile.getDistributedMember());
memberProfiles.put(profile.getDistributedMember(), profile);
}
else
if (profile.dataPolicy.withStorage()) {
// don't bother asking proxy members for initial image
others.add(profile.getDistributedMember());
memberProfiles.put(profile.getDistributedMember(), profile);
} else {
empties.add(profile.getDistributedMember());
}
}
InitialImageAdvice advice = new InitialImageAdvice(replicates, others,
preloaded, empties, uninitialized, memberProfiles);
if (log.fineEnabled()) {
log.fine(advice.toString());
}
return advice;
}
/**
* returns the set of all the members in the system which requires old values
* and are not yet finished with initialization (including GII).
* @since 5.5
*/
public Set adviseRequiresOldValueInCacheOp() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
return cp.requiresOldValueInEvents && !cp.regionInitialized;
}
});
}
public Set adviseDBSynchOrAsyncListenerMembers() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile) profile;
return cp.hasDBSynchOrAsyncEventListener;
}
});
}
// moved adviseProfileExchange to DistributionAdvisor
// moved getProfile to DistributionAdvisor
// moved exchangeProfiles to DistributionAdvisor
// moved getDistributionManager to DistributionAdvisor
/** Instantiate new distribution profile for this member */
@Override
protected Profile instantiateProfile(
InternalDistributedMember memberId, int version) {
return new CacheProfile(memberId, version);
}
@Override
protected boolean evaluateProfiles(Profile newProfile, Profile oldProfile) {
boolean result = super.evaluateProfiles(newProfile, oldProfile);
if (result) {
CacheProfile newCP = (CacheProfile)newProfile;
CacheProfile oldCP = (CacheProfile)oldProfile;
if ((oldCP == null || !oldCP.regionInitialized) && newCP.regionInitialized) {
// invoke membership listeners, if any
CacheDistributionAdvisee advisee = (CacheDistributionAdvisee)getAdvisee();
advisee.remoteRegionInitialized(newCP);
}
}
return result;
}
/**
* Profile information for a remote counterpart.
*/
public static class CacheProfile extends DistributionAdvisor.Profile {
public DataPolicy dataPolicy = DataPolicy.REPLICATE;
public InterestPolicy interestPolicy = InterestPolicy.DEFAULT;
public boolean hasCacheLoader = false;
public boolean hasCacheWriter = false;
public boolean hasCacheListener = false;
public Scope scope = Scope.DISTRIBUTED_NO_ACK;
public boolean inRecovery = false;
public Set gatewaySenderIds = Collections.emptySet();
public Set asyncEventQueueIds = Collections.emptySet();
public Set activeSerialGatewaySenderIds = null;
public Set activeSerialAsyncQueueIds = null;
public boolean hasDBSynchOrAsyncEventListener = false;
/**
* Will be null if the profile doesn't need to have the attributes
*/
public SubscriptionAttributes subscriptionAttributes = null;
public boolean isPartitioned = false;
public boolean isGatewayEnabled = false;
public boolean isPersistent = false;
public boolean isOffHeap = false;
// moved initialMembershipVersion to DistributionAdvisor.Profile
// moved serialNumber to DistributionAdvisor.Profile
/**
* this member's client interest / continuous query profile. This is used
* for event processing to reduce the number of times CQs are executed and
* to have the originating member for an event pay the cpu cost of executing
* filters on the event.
*/
public FilterProfile filterProfile;
/**
* Some cache listeners require old values in cache operation messages,
* at least during GII
*/
public boolean requiresOldValueInEvents;
/**
* Whether the region has completed initialization, including GII.
* This information may be incorrect for a PartitionedRegion, but
* may be relied upon for DistributedRegions (including BucketRegions)
*
* @since prpersist this field is now overloaded for partitioned regions with persistence.
* In the case of pr persistence, this field indicates that the region has finished
* recovery from disk.
*/
public boolean regionInitialized;
/**
* True when member is still not ready to receive cache operations. Note
* that {@link #regionInitialized} may be still true so other members can
* proceed with GII etc. Currently used by GemFireXD to indicate that DDL
* replay is in progress and so cache operations/functions should not be
* routed to that node.
*/
public boolean memberUnInitialized = false;
/**
* True when a members persistent store is initialized. Note that
* regionInitialized may be true when this is false in the case of createBucketAtomically.
* With createBucketAtomically, the peristent store is not created until
* the EndBucketCreationMessage is sent.
*/
public boolean persistenceInitialized;
public PersistentMemberID persistentID;
/**
* This member has any cache servers. This is not actively maintained for
* local profiles (i.e., a profile representing this vm)
*/
public boolean hasCacheServer = false;
/** for internal use, required for DataSerializer.readObject */
public CacheProfile() {
}
/** used for routing computation */
public CacheProfile(FilterProfile localProfile) {
this.filterProfile = localProfile;
}
public CacheProfile(InternalDistributedMember memberId, int version) {
super(memberId, version);
}
public CacheProfile(CacheProfile toCopy) {
super(toCopy.getDistributedMember(), toCopy.version);
setIntInfo(toCopy.getIntInfo());
}
/** Return the profile data information that can be stored in an int */
protected int getIntInfo() {
int s = 0;
if (this.dataPolicy.withReplication()) {
s |= REPLICATE_MASK;
if (isPersistent()) {
s |= PERSISTENT_MASK;
}
} else {
if (this.dataPolicy == DataPolicy.EMPTY) s |= PROXY_MASK;
if (this.dataPolicy == DataPolicy.PRELOADED) s |= PRELOADED_MASK;
}
if (this.subscriptionAttributes != null
&& this.subscriptionAttributes.getInterestPolicy().isAll()) {
s |= INTEREST_MASK;
}
if (this.hasCacheLoader) s |= LOADER_MASK;
if (this.hasCacheWriter) s |= WRITER_MASK;
if (this.hasCacheListener) s |= LISTENER_MASK;
if (this.scope.isDistributedAck()) s |= DIST_ACK_MASK;
if (this.scope.isGlobal()) s |= GLOBAL_MASK;
if (this.inRecovery) s |= IN_RECOVERY_MASK;
if (this.isPartitioned) s |= IS_PARTITIONED_MASK;
if (this.isGatewayEnabled) s |= IS_GATEWAY_ENABLED_MASK;
if (this.isPersistent) s |= PERSISTENT_MASK;
if (this.regionInitialized) s|= REGION_INITIALIZED_MASK;
if (this.memberUnInitialized) s |= MEMBER_UNINITIALIZED_MASK;
if (this.persistentID != null) s|= PERSISTENT_ID_MASK;
if (this.hasCacheServer) s|= HAS_CACHE_SERVER_MASK;
if (this.requiresOldValueInEvents) s|= REQUIRES_OLD_VALUE_MASK;
if (this.persistenceInitialized) s|= PERSISTENCE_INITIALIZED_MASK;
if (!this.gatewaySenderIds.isEmpty()) s |= GATEWAY_SENDER_IDS_MASK;
if (!this.asyncEventQueueIds.isEmpty()) s |= ASYNC_EVENT_QUEUE_IDS_MASK;
if (this.activeSerialGatewaySenderIds != null) s |= HAS_ACTIVE_GATEWAY_SENDER_MASK;
if (this.activeSerialAsyncQueueIds != null) s |= HAS_ACTIVE_ASYNC_QUEUE_MASK;
if (this.isOffHeap) s |= IS_OFF_HEAP_MASK;
if (this.hasDBSynchOrAsyncEventListener) s |= HAS_DB_SYNCH_OR_ASYNC_LISTENER_MASK;
Assert.assertTrue(!this.scope.isLocal());
return s;
}
private boolean hasGatewaySenderIds(int bits) {
return (bits & GATEWAY_SENDER_IDS_MASK) != 0;
}
private boolean hasAsyncEventQueueIds(int bits) {
return (bits & ASYNC_EVENT_QUEUE_IDS_MASK) != 0;
}
/**
* @param bits
* @return true if the serialized message has a persistentID
*/
private boolean hasPersistentID(int bits) {
return (bits & PERSISTENT_ID_MASK) != 0;
}
public boolean isPersistent() {
return this.dataPolicy.withPersistence();
}
/** Set the profile data information that is stored in a short */
protected void setIntInfo(int s) {
if ((s & REPLICATE_MASK) != 0) {
if ((s & PERSISTENT_MASK) != 0) {
this.dataPolicy = DataPolicy.PERSISTENT_REPLICATE;
}
else {
this.dataPolicy = DataPolicy.REPLICATE;
}
}
else
if ((s & PROXY_MASK) != 0) {
this.dataPolicy = DataPolicy.EMPTY;
}
else
if ((s & PRELOADED_MASK) != 0) {
this.dataPolicy = DataPolicy.PRELOADED;
}
else { // CACHED
this.dataPolicy = DataPolicy.NORMAL;
}
if((s & IS_PARTITIONED_MASK) != 0) {
if((s & PERSISTENT_MASK) != 0) {
this.dataPolicy = DataPolicy.PERSISTENT_PARTITION;
} else {
this.dataPolicy = DataPolicy.PARTITION;
}
}
if ((s & INTEREST_MASK) != 0) {
this.subscriptionAttributes = new SubscriptionAttributes(InterestPolicy.ALL);
} else {
this.subscriptionAttributes = new SubscriptionAttributes(InterestPolicy.CACHE_CONTENT);
}
this.hasCacheLoader = (s & LOADER_MASK) != 0;
this.hasCacheWriter = (s & WRITER_MASK) != 0;
this.hasCacheListener = (s & LISTENER_MASK) != 0;
this.scope = (s & DIST_ACK_MASK) != 0 ? Scope.DISTRIBUTED_ACK :
((s & GLOBAL_MASK) != 0 ? Scope.GLOBAL : Scope.DISTRIBUTED_NO_ACK);
this.inRecovery = (s & IN_RECOVERY_MASK) != 0;
this.isPartitioned = (s & IS_PARTITIONED_MASK) != 0;
this.isGatewayEnabled = (s & IS_GATEWAY_ENABLED_MASK) != 0;
this.isPersistent = (s & PERSISTENT_MASK) != 0;
this.regionInitialized = ( (s & REGION_INITIALIZED_MASK) != 0 );
this.memberUnInitialized = (s & MEMBER_UNINITIALIZED_MASK) != 0;
this.hasCacheServer = ( (s & HAS_CACHE_SERVER_MASK) != 0 );
this.requiresOldValueInEvents = ((s & REQUIRES_OLD_VALUE_MASK) != 0);
this.persistenceInitialized = (s & PERSISTENCE_INITIALIZED_MASK) != 0;
this.isOffHeap = (s & IS_OFF_HEAP_MASK) != 0;
this.hasDBSynchOrAsyncEventListener = (s & HAS_DB_SYNCH_OR_ASYNC_LISTENER_MASK) != 0;
}
/**
* Sets the SubscriptionAttributes for the region that this profile is on
* @since 5.0
*/
public void setSubscriptionAttributes(SubscriptionAttributes sa) {
this.subscriptionAttributes = sa;
}
/**
* Return true if cached or allEvents and a listener
*/
public boolean cachedOrAllEventsWithListener() {
// to fix bug 36804 to ignore hasCacheListener
// return this.dataPolicy.withStorage() ||
// (allEvents() && this.hasCacheListener);
return cachedOrAllEvents();
}
/**
* Return true if cached or allEvents
*/
public final boolean cachedOrAllEvents() {
return this.dataPolicy.withStorage() || allEvents();
}
/**
* Return true if subscribed to all events
*/
public final boolean allEvents() {
return this.subscriptionAttributes.getInterestPolicy().isAll();
}
/**
* Used to process an incoming cache profile.
*/
@Override
public void processIncoming(DistributionManager dm, String adviseePath,
boolean removeProfile, boolean exchangeProfiles,
final List replyProfiles, LogWriterI18n logger) {
try {
Assert.assertTrue(adviseePath != null, "adviseePath was null");
LocalRegion lclRgn;
int oldLevel = LocalRegion
.setThreadInitLevelRequirement(LocalRegion.ANY_INIT);
try {
lclRgn = LocalRegion.getRegionFromPath(dm.getSystem(), adviseePath);
} finally {
LocalRegion.setThreadInitLevelRequirement(oldLevel);
}
// remove failed event handling for GemFireXD
if (lclRgn != null && this.regionInitialized
&& (lclRgn instanceof DistributedRegion)) {
((DistributedRegion)lclRgn)
.clearFailedEventsForMember(getDistributedMember());
}
if (lclRgn instanceof CacheDistributionAdvisee) {
if (lclRgn.isUsedForPartitionedRegionBucket()) {
if (!((BucketRegion)lclRgn).isPartitionedRegionOpen()) {
return;
}
}
handleCacheDistributionAdvisee((CacheDistributionAdvisee)lclRgn,
adviseePath, removeProfile, exchangeProfiles, true,
replyProfiles, logger);
}
else {
if (lclRgn == null) {
handleCacheDistributionAdvisee(PartitionedRegionHelper
.getProxyBucketRegion(GemFireCacheImpl.getInstance(), adviseePath,
false), adviseePath, removeProfile, exchangeProfiles,
false, replyProfiles, logger);
}
else {
if (logger.fineEnabled())
logger.fine("While processing UpdateAttributes message, "
+ "region has local scope: " + adviseePath);
}
}
} catch (PRLocallyDestroyedException fre) {
if (logger.fineEnabled()) {
logger.fine(" /// " + this);
}
} catch (RegionDestroyedException e) {
if (logger.fineEnabled())
logger.fine(" /// " + this);
}
}
/**
* Attempts to process this message with the specified
* CacheDistributionAdvisee
.
*
* @param cda
* the CacheDistributionAdvisee to apply this profile to
* @param isRealRegion
* true if CacheDistributionAdvisee is a real region
*/
private void handleCacheDistributionAdvisee(CacheDistributionAdvisee cda,
String adviseePath, boolean removeProfile, boolean exchangeProfiles,
boolean isRealRegion, final List replyProfiles,
LogWriterI18n logger) {
if (cda != null) {
handleDistributionAdvisee(cda, removeProfile, isRealRegion
&& exchangeProfiles, replyProfiles);
if (logger.fineEnabled()) {
logger.fine("While processing UpdateAttributes message, "
+ "handled advisee: " + cda);
}
}
else if (logger.fineEnabled()) {
logger.fine("While processing UpdateAttributes message, "
+ "region not found: " + adviseePath);
}
}
@Override
public int getDSFID() {
return CACHE_PROFILE;
}
@Override
public void toData(DataOutput out) throws IOException {
super.toData(out);
out.writeInt(getIntInfo());
if(persistentID != null) {
InternalDataSerializer.invokeToData(persistentID, out);
}
if (!gatewaySenderIds.isEmpty()) {
writeSet(gatewaySenderIds, out);
}
if (!asyncEventQueueIds.isEmpty()) {
writeSet(asyncEventQueueIds, out);
}
DataSerializer.writeObject(this.filterProfile, out);
if (this.activeSerialGatewaySenderIds != null) {
DataSerializer.writeObject(this.activeSerialGatewaySenderIds, out);
}
if (this.activeSerialAsyncQueueIds != null) {
DataSerializer.writeObject(this.activeSerialAsyncQueueIds, out);
}
}
private void writeSet(Set set, DataOutput out) throws IOException {
// to fix bug 47205 always serialize the Set as a HashSet.
out.writeByte(DSCODE.HASH_SET);
InternalDataSerializer.writeSet(set, out);
}
@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
super.fromData(in);
int bits = in.readInt();
setIntInfo(bits);
if(hasPersistentID(bits)) {
persistentID = new PersistentMemberID();
InternalDataSerializer.invokeFromData(persistentID, in);
}
if (hasGatewaySenderIds(bits)) {
gatewaySenderIds = DataSerializer.readObject(in);
}
if (hasAsyncEventQueueIds(bits)) {
asyncEventQueueIds = DataSerializer.readObject(in);
}
this.filterProfile = DataSerializer.readObject(in);
if ((bits & HAS_ACTIVE_GATEWAY_SENDER_MASK) != 0) {
this.activeSerialGatewaySenderIds = DataSerializer.readObject(in);
}
if ((bits & HAS_ACTIVE_ASYNC_QUEUE_MASK) != 0) {
this.activeSerialAsyncQueueIds = DataSerializer.readObject(in);
}
}
@Override
public StringBuilder getToStringHeader() {
return new StringBuilder("CacheProfile");
}
@Override
public void fillInToString(StringBuilder sb) {
super.fillInToString(sb);
sb.append("; dataPolicy=" + this.dataPolicy);
sb.append("; hasCacheLoader=" + this.hasCacheLoader);
sb.append("; hasCacheWriter=" + this.hasCacheWriter);
sb.append("; hasCacheListener=" + this.hasCacheListener);
sb.append("; hasCacheServer=").append(this.hasCacheServer);
sb.append("; scope=" + this.scope);
sb.append("; regionInitialized=").append(
String.valueOf(this.regionInitialized));
sb.append("; memberUnInitialized=").append(
String.valueOf(this.memberUnInitialized));
sb.append("; inRecovery=" + this.inRecovery);
sb.append("; subcription=" + this.subscriptionAttributes);
sb.append("; isPartitioned=" + this.isPartitioned);
sb.append("; isGatewayEnabled=" + this.isGatewayEnabled);
sb.append("; isPersistent=" + this.isPersistent);
sb.append("; persistentID=" + this.persistentID);
sb.append("; persistenceInitialized=")
.append(this.persistenceInitialized);
if (this.filterProfile != null) {
sb.append("; ").append(this.filterProfile);
}
sb.append("; gatewaySenderIds =" + this.gatewaySenderIds);
sb.append("; asyncEventQueueIds =" + this.asyncEventQueueIds);
if (this.activeSerialGatewaySenderIds != null) {
sb.append("; activeSerialGatewaySenderIds=").append(
this.activeSerialGatewaySenderIds);
}
if (this.activeSerialAsyncQueueIds != null) {
sb.append("; activeSerialAsyncQueueIds=").append(
this.activeSerialAsyncQueueIds);
}
sb.append("; IsOffHeap=" + this.isOffHeap);
sb.append("; hasDBSynchOrAsyncEventListener=" + this.hasDBSynchOrAsyncEventListener);
}
}
/** Recipient information used for getInitialImage operation */
public static class InitialImageAdvice {
public Set getOthers() {
return this.others;
}
public void setOthers(Set others) {
this.others = others;
}
public Set getReplicates() {
return this.replicates;
}
public Set getPreloaded() {
return this.preloaded;
}
public Set getEmpties() {
return this.empties;
}
public Set getUninitialized() {
return this.uninitialized;
}
/** Set of replicate recipients */
protected final Set replicates;
/** Set of peers that are preloaded */
protected final Set preloaded;
/** Set of tertiary recipients which are not replicates, in which case
* they should all be queried and a superset taken of their images.
* To be used only if the image cannot be obtained from the replicates set.
*/
protected Set others;
/** Set of members that might be data feeds and have EMPTY data policy */
protected final Set empties;
/** Set of members that may not have finished initializing their caches */
protected final Set uninitialized;
private final Map memberProfiles;
protected InitialImageAdvice(Set replicates, Set others,
Set preloaded,
Set empties,
Set uninitialized,
Map memberProfiles) {
this.replicates = replicates;
this.others = others;
this.preloaded = preloaded;
this.empties = empties;
this.uninitialized = uninitialized;
this.memberProfiles = memberProfiles;
}
@Override
public String toString() {
return "InitialImageAdvice("
+ "replicates=" + this.replicates
+ "; others=" + this.others
+ "; preloaded=" + this.preloaded
+ "; empty=" + this.empties
+ "; initializing=" + this.uninitialized
+ ")";
}
}
// moved putProfile, doPutProfile, and putProfile to DistributionAdvisor
// moved isNewerProfile to DistributionAdvisor
// moved isNewerSerialNumber to DistributionAdvisor
// moved forceNewMembershipVersion to DistributionAdvisor
// moved startOperation to DistributionAdvisor
// moved endOperation to DistributionAdvisor
/**
* Provide only the new replicates given a set of existing
* memberIds
* @param oldRecipients the Set
of memberIds that have received the message
* @return the set of new replicate's memberIds
* @since 5.1
*/
public Set adviseNewReplicates(final Set oldRecipients)
{
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy.withReplication() && !cp.memberUnInitialized
&& !oldRecipients.contains(cp.getDistributedMember())) {
return true;
}
return false;
}
});
}
// moved waitForCurrentOperations to DistributionAdvisor
// moved removeId, doRemoveId, removeIdWithSerial, and updateRemovedProfiles to DistributionAdvisor
/**
* Provide all the replicates including persistent replicates.
*
* @return the set of replicate's memberIds
* @since 5.8
*/
public Set adviseReplicates() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy.withReplication()) {
return true;
}
return false;
}
});
}
/**
* Provide only the preloadeds given a set of existing memberIds
*
* @return the set of preloaded's memberIds
* @since prPersistSprint1
*/
public Set advisePreloadeds() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy.withPreloaded()) {
return true;
}
return false;
}
});
}
/**
* return the set of all members who have AsyncEventQueues defined and are
* active for this region
*
* @since GemFireXD
*/
@SuppressWarnings("rawtypes")
public final Set adviseAsyncEventQueue() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
return cp.activeSerialAsyncQueueIds != null
&& cp.activeSerialAsyncQueueIds.size() > 0;
}
});
}
protected final boolean profileHasSerialAEQorWAN(CacheProfile cp) {
Set ids;
return ((ids = cp.activeSerialAsyncQueueIds) != null && ids.size() > 0)
|| ((ids = cp.activeSerialGatewaySenderIds) != null && ids.size() > 0);
}
/**
* return the set of all members who have serial AsyncEventQueue or
* GatewaySender defined and are active for this region
*
* @since GemFireXD
*/
@SuppressWarnings("rawtypes")
public final Set adviseSerialAsyncEventQueueOrGatewaySender() {
return adviseFilter(new Filter() {
@Override
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
return profileHasSerialAEQorWAN(cp);
}
});
}
/**
* return the set of all members who have serial AsyncEventQueues or
* GatewaySenders with given IDs defined and are active for this region
*
* @since GemFireXD
*/
@SuppressWarnings("rawtypes")
public final Set adviseSerialAsyncEventQueueOrGatewaySender(
final String[] asyncIds, final String[] gatewayIds) {
return adviseFilter(new Filter() {
private final boolean containsAny(final Set ids,
final String[] searchIds) {
for (String searchId : searchIds) {
if (ids.contains(searchId)) {
return true;
}
}
return false;
}
@Override
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
Set ids;
if (asyncIds != null) {
if ((ids = cp.activeSerialAsyncQueueIds) != null
&& containsAny(ids, asyncIds)) {
return true;
}
}
if (gatewayIds != null) {
return ((ids = cp.activeSerialGatewaySenderIds) != null && containsAny(ids,
gatewayIds));
}
return false;
}
});
}
/**
* Provide only the empty's (having DataPolicy.EMPTY) given a set of existing
* memberIds
*
* @return the set of replicate's memberIds
* @since 5.8
*/
public Set adviseEmptys() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy == DataPolicy.EMPTY) {
return true;
}
return false;
}
});
}
/**
* Provide only the normals (having DataPolicy.NORMAL) given a set of existing memberIds
*
* @return the set of normal's memberIds
* @since 5.8
*/
public Set adviseNormals() {
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
if (cp.dataPolicy == DataPolicy.NORMAL) {
return true;
}
return false;
}
});
}
@Override
protected void profileRemoved(Profile profile) {
getLogWriter().fine("CDA: removing profile "+profile);
if (getAdvisee() instanceof LocalRegion && profile != null) {
((LocalRegion)getAdvisee()).removeMemberFromCriticalList(profile.getDistributedMember());
}
}
/**
* Returns the list of all persistent members.
* For most cases, adviseInitializedPersistentMembers is more appropriate. These
* method includes members that are still in the process of GII.
*/
@SuppressWarnings("unchecked")
public Map
advisePersistentMembers() {
initializationGate();
THashMap result = new THashMap();
Profile[] snapshot = this.profiles;
for (Profile profile : snapshot) {
CacheProfile cp = (CacheProfile)profile;
if (cp.persistentID != null) {
result.put(cp.getDistributedMember(), cp.persistentID);
}
}
return result;
}
@SuppressWarnings("unchecked")
public Map
adviseInitializedPersistentMembers() {
initializationGate();
THashMap result = new THashMap();
Profile[] snapshot = this.profiles;
for (Profile profile : snapshot) {
CacheProfile cp = (CacheProfile)profile;
if (cp.persistentID != null && cp.persistenceInitialized) {
result.put(cp.getDistributedMember(), cp.persistentID);
}
}
return result;
}
public Set adviseCacheServers() {
getAdvisee().getCancelCriterion().checkCancelInProgress(null);
return adviseFilter(new Filter() {
public boolean include(Profile profile) {
assert profile instanceof CacheProfile;
CacheProfile cp = (CacheProfile)profile;
return cp.hasCacheServer;
}
});
}
//Overrided for bucket regions. This listener also receives events
//about PR joins and leaves.
public void addMembershipAndProxyListener(MembershipListener listener) {
addMembershipListener(listener);
}
public void removeMembershipAndProxyListener(MembershipListener listener) {
removeMembershipListener(listener);
}
@Override
public boolean removeId(ProfileId memberId, boolean crashed,
boolean destroyed, boolean fromMembershipListener) {
boolean isPersistent = false;
DiskStoreID persistentId = null;
CacheDistributionAdvisee advisee = (CacheDistributionAdvisee)getAdvisee();
if (advisee.getAttributes().getDataPolicy().withPersistence()) {
isPersistent = true;
CacheProfile profile = (CacheProfile)getProfile(memberId);
if (profile != null && profile.persistentID != null) {
persistentId = ((CacheProfile)getProfile(memberId)).persistentID.diskStoreId;
}
}
boolean result = super.removeId(memberId, crashed, destroyed, fromMembershipListener);
// bug #48962 - record members that leave during GII so IIOp knows about them
if (advisee instanceof DistributedRegion) {
DistributedRegion r = (DistributedRegion)advisee;
if (!r.isInitialized() && !r.isUsedForPartitionedRegionBucket()) {
if (r.getLogWriterI18n().fineEnabled()) {
r.getLogWriterI18n().fine("recording that " + memberId +" has left during initialization of " + r.getName());
}
ImageState state = r.getImageState();
if (isPersistent) {
if (persistentId != null) {
state.addLeftMember(persistentId);
}
} else {
state.addLeftMember((InternalDistributedMember)memberId);
}
}
}
return result;
}
}