You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by nn...@apache.org on 2020/06/02 22:06:09 UTC

[geode] branch feature/GEODE-7665 updated (e960021 -> 8ae9f29)

This is an automated email from the ASF dual-hosted git repository.

nnag pushed a change to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git.


    omit e960021  GEODE-7678 (2nd PR) - Support for cache-listener and client-notification for Partitioned Region Clear operation  (#5124)
    omit 81102ce  GEODE-7667: Fixing test to include PR clear help text.
    omit 780567a  GEODE-7894: Moving expiry tasks to AbstractRegion.
    omit 56679c6  GEODE-7676: Conversion of duration to seconds.
    omit 1083198  GEODE-7667: Add a 'clear' gfsh command for PR and RR clear (#4818)
    omit 0ea8737  GEODE-7676: Add PR clear with expiration tests (#4970)
    omit f61c16a  GEODE-7983: Clear region writer callbacks should not be invoked for bucket regions (#4954)
    omit 3eae78e  GEODE-7912: cacheWriter should be triggered when PR.clear (#4882)
    omit bc38e50  PR.clear's event id should be created and used in BR (#4805)
    omit 362bad5  GEODE-7682: add PR.clear  API (#4755)
    omit 7ad1190  GEODE-7683: introduce BR.cmnClearRegion
     add 92b2bc7  GEODE-8070: rework handling of "any" in SSLUtils (#5075)
     add a5c8548  GEODE-7702: the removeAll from NORMAL should not be changed to use RemoteDestroyMessage like putAll (#5091)
     add 4c5788d  GEODE-8103: Renames SniSocketFactory to SniProxySocketFactory (#5092)
     add 79c9dd4  GEODE-8091: fix AuthenticationRequiredException when starting a locat… (#5071)
     add 19b900f  GEODE-8097: expects at least one callback instead of exactly one. (#5093)
     add 7ed7caf  GEODE-8107: Sort GCE instances by creationTimestamp for concourse (#5094)
     add 904a08a  GEODE-8090: implement function/delta for redis Hash ops (#5085)
     add 15df6a8  GEODE-8091: fix AuthenticationRequiredException when starting a locator (#5098)
     add 9e90aee  GEODE-8111: Fix create gw receiver --manual-start doc (#5097)
     add 5088854  GEODE-8113: change getMap to never return null (#5101)
     add 8a51ce2  GEODE-8098: Refactor CommandFunction (#5082)
     add a798009  GEODE-8120: Make GeodeRedisServer internal (#5107)
     add 5a74a33  GEODE-8124: Fix the error logging to display stacktrace (#5109)
     add d402351  GEODE-8114: Refactor RedisSet and RedisHash (#5100)
     add cf063bf  GEODE-8123: Allow Redis to start on a random port (#5108)
     add 2842ce0  GEODE-8126: Add ExecutionException tests to ExecutorServiceRuleTest (#5113)
     add f057b5c  GEODE-8125: Extract AccessibleErrorCollector from SharedErrorCollector (#5112)
     add ba8a552  GEODE-8132: Remove ability to set Redis region type (#5117)
     add a235c7c  GEODE-8078: log and report error at the correct place. (#5111)
     add 4fff1f9  GEODE-8094: Create HA test to ensure Spring Boot sessions expire correctly (#5079)
     add 32a0177  GEODE-8133: Fix task chaining for 'devBuild' (#5118)
     add e084aa4  GEODE-8130: use a single region for redis Sets and Hashes  (#5120)
     add 0d602cc  GEODE-8035: Parallel Disk Store Recovery when Cluster Restarts (#5014)
     add 334e24f  GEODE-8096: Providing unique names for the JARs in the tests (#5119)
     add fff9853  GEODE-8069: fix release script issues (#5050)
     add 4c12d70  GEODE-8122: Update Geode Redis API docs (#5122)
     add b38ae30  GEODE-7792: configure logging for geode-membership integration tests (#5116)
     add 1af3be3  GEODE-8100: update cluster-management-service documentation (#5121)
     add 6aa2420  Introduce RedisResponse to SET executors (#5114)
     add 7e222df  GEODE-8147: change redis DELETE and EXISTS to use Function+Delta (#5128)
     add 47a5709  GEODE-8095: refactor operation BiFunction into a specific OperationPerformer interface (#5135)
     add aca029e  GEODE-8100: Update cluster management service docs - style edit (#5141)
     add 7538de5  GEODE-8167: bump spring security to recommended version (#5144)
     add 19d5f78  GEODE-7458: Adding option in gfsh command "start gateway sender" to control clearing of existing queues (#4387)
     add c3c226a  GEODE-8119:closing threads when offline disk store is executed (#5106)
     add 07bf3dd  GEODE-8150: Downgrade classgraph to 4.8.52 (#5138)
     add d08847b  GEODE-8112: Add --member option in query command. (#5102)
     add 9a0563e  GEODE-8170: change all hash and set commands to use function (#5125)
     add 0f8da9e  GEODE-8145: Add Redis configuration properties to gemfire_properties.html (#5130)
     add f2392d0  GEODE-8146: use latest winrm in tools image (#5134)
     add 358fd70  GEODE-8131: reader thread blocked attempting to issue an alert (#5132)
     add e0cbd78  GEODE-8127: ensure that redis function executes on primary  (#5133)
     add d47e073  GEODE-8138: Improve semantics of the redis-port option (#5142)
     add 0a7f8ae  GEODE-8168: Redis pipelined command responses can be corrupted (#5145)
     add af1ea6d  GEODE-8151: Convert hash commands to return RedisResponse (#5140)
     add f243c4d  Revert GEODE-8127: the test is flakey (#5153)
     add a05b86d  GEODE-8175: remove unsupported redis commands (#5146)
     add 03355b9  GEODE-8175: fix compile error (#5156)
     add e5e803e  GEODE-8180: add 1.14 to management wiki (#5154)
     add 99b12ed  GEODE-8108: Remove System.out.println calls from geode-redis (#5149)
     add c79905f  Revert "GEODE-8119:closing threads when offline disk store is executed (#5106)" (#5158)
     add e432855  GEODE-7971: Gw sender deliver TX events atomically to Gw receivers (#4928)
     add b22df8c  GEODE-8144: endpoint identification in servers is not working (#5131)
     add 253d667  GEODE-8136: Move UncheckedUtils to geode-common (#5123)
     add 5e00b10  GEODE-8134: convert String commands to use Function+Delta (#5160)
     add bef07b3  GEODE-8174: Fix ConcurrentModificationException when using JTA transaction. (#5161)
     add 17dd67a  GEODE-8182: change String commands to use one region (#5165)
     add a185267  Feature/geode 8144 (#5164)
     add 53d1631  GEODE-8171: javadoc for putAll need to have accurate exception (#5147)
     add 42c1164  GEODE-8144 another attempt to fix a failing test (#5172)
     add dd990e8  GEODE-8193: Broken link in statistics list (#5166)
     add bd2d118  GEODE-7864: Override the default implementation of write(byte[],int,int) (#4871)
     add 0fd56e4  GEODE-7846: Replace all uses of hardcoded / with Region.SEPARATOR (#5157)
     add 2d85af4  GEODE-8166: reimplement redis expiration to use new data model (#5174)
     add 83b40f5  The RedisData region name now starts with "__". (#5181)
     add 343e114  GEODE-8127: Reintroduces changes that account for primary bucket changing (#5179)
     add 973750e  ByteArrayWrapper now implementes DataSerializableFixedID which should save us 40 bytes each time it is serialized. (#5180)
     add 57cc3c7  GEODE-6070: Fix ShutdownCommandOverHttpDUnitTest flakiness (#5162)
     add 2883e97  GEODE-8205: feature flag unsupported Redis commands (#5185)
     add 0fdcd5b  GEODE-8211: fix flaky ShutdownIntegrationTest (#5193)
     add 4090cef  repackaged GlobPattern (#5190)
     add 426d7fd  GEODE-8206: CI Failure: ReconnectWithClusterConfigurationDUnitTest.testReconnectAfterMeltdown hang (#5192)
     add c7bb1f3  GEODE-7759: Print out the Passing token file contents. (#4665)
     add 4f559fc  GEODE-8203: Provide ability to prevent disabling geode console appender (#5183)
     add 270722f  fixup: image for gcs-json-resource was doubly-merged into CI (#5198)
     add 371ee4e  GEODE-8203: Removed camel casing for system property (#5197)
     new 22ca1ab  GEODE-7683: introduce BR.cmnClearRegion
     new 8f1612b  GEODE-7682: add PR.clear  API (#4755)
     new f868c0f  PR.clear's event id should be created and used in BR (#4805)
     new 653b44d  GEODE-7912: cacheWriter should be triggered when PR.clear (#4882)
     new 9a6cc48  GEODE-7983: Clear region writer callbacks should not be invoked for bucket regions (#4954)
     new f3168e9  GEODE-7676: Add PR clear with expiration tests (#4970)
     new b7b3223  GEODE-7667: Add a 'clear' gfsh command for PR and RR clear (#4818)
     new df4cb91  GEODE-7676: Conversion of duration to seconds.
     new 359c3bf  GEODE-7894: Moving expiry tasks to AbstractRegion.
     new b56bbd7  GEODE-7667: Fixing test to include PR clear help text.
     new 8ae9f29  GEODE-7678 (2nd PR) - Support for cache-listener and client-notification for Partitioned Region Clear operation  (#5124)

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (e960021)
            \
             N -- N -- N   refs/heads/feature/GEODE-7665 (8ae9f29)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/test/resources/expected-pom.xml            |   24 +-
 build.gradle                                       |    1 +
 .../gradle/plugins/DependencyConstraints.groovy    |    6 +-
 ci/images/alpine-tools/Dockerfile                  |   22 +-
 ci/pipelines/geode-build/jinja.template.yml        |    9 +-
 ci/pipelines/meta/deploy_meta.sh                   |    1 -
 ci/pipelines/meta/jinja.template.yml               |    1 +
 ci/pipelines/shared/jinja.variables.yml            |    2 +-
 ci/resource-types/gce-instances-resource/check     |    3 +-
 dev-tools/release/commit_rc.sh                     |    5 +-
 dev-tools/release/create_support_branches.sh       |   43 +-
 dev-tools/release/end_of_support.sh                |    2 +-
 dev-tools/release/license_review.sh                |    4 +-
 dev-tools/release/prepare_rc.sh                    |   14 +-
 dev-tools/release/promote_rc.sh                    |   12 +-
 dev-tools/release/set_copyright.sh                 |    2 +-
 dev-tools/release/set_versions.sh                  |   36 +-
 .../modules/util/RegionHelperIntegrationTest.java  |    3 +-
 ...icatedRegionEntriesFunctionIntegrationTest.java |    3 +-
 .../web/controllers/AddFreeItemToOrders.java       |    5 +-
 .../web/controllers/GetDeliveredOrders.java        |    5 +-
 .../MissingDiskStoreAcceptanceTest.java            |    3 +-
 .../client/sni/ClientSNICQAcceptanceTest.java      |    3 +-
 .../client/sni/DualServerSNIAcceptanceTest.java    |    3 +-
 .../client/sni/SingleServerSNIAcceptanceTest.java  |    3 +-
 ...rStartupRedundancyRecoveryNotificationTest.java |    7 +-
 .../cli/commands/ConfigureEvictionThroughGfsh.java |   46 +-
 .../org/apache/geode/client/sni/docker-compose.yml |    1 +
 .../client/sni/geode-config/gemfire.properties     |    1 +
 .../client/sni/geode-config/gfsecurity.properties  |    2 +-
 .../sni/geode-config/locator-maeve-keystore.jks    |  Bin 2048 -> 3525 bytes
 .../geode-config/server-clementine-keystore.jks    |  Bin 2059 -> 3537 bytes
 .../sni/geode-config/server-dolores-keystore.jks   |  Bin 2050 -> 3528 bytes
 .../geode/client/sni/geode-config/truststore.jks   |  Bin 8095 -> 1126 bytes
 .../geode/client/sni/scripts/geode-starter-2.gfsh  |    8 +-
 .../geode/client/sni/scripts/geode-starter.gfsh    |    6 +-
 .../management/JQFilterVerificationDUnitTest.java  |    3 +-
 .../cli/commands/RunOutOfMemoryFunction.java       |    4 +-
 .../rest/ClientClusterManagementSSLTest.java       |    3 +-
 .../rest/ListIndexManagementDUnitTest.java         |   25 +-
 .../rest/ListIndexOnPartitionRegionTest.java       |    5 +-
 .../rest/RebalanceManagementDunitTest.java         |    7 +-
 .../internal/rest/RegionManagementDunitTest.java   |    3 +-
 .../controllers/RestAPIsAndInterOpsDUnitTest.java  |    9 +-
 .../rest/internal/web/RestRegionAPIDUnitTest.java  |   11 +-
 .../web/RestSecurityPostProcessorTest.java         |    6 +-
 .../pulse/EmbeddedPulseClusterSecurityTest.java    |    3 +-
 .../geode/tools/pulse/PulseDataExportTest.java     |   12 +-
 .../integrationTest/resources/assembly_content.txt |    8 +-
 .../resources/dependency_classpath.txt             |    2 +-
 geode-assembly/src/main/dist/LICENSE               |    2 +-
 .../tools/pulse/ui/PulseAcceptanceAuthTest.java    |    4 +-
 .../tools/pulse/ui/PulseAcceptanceNoAuthTest.java  |    4 +-
 .../tools/pulse/ui/PulseAcceptanceTestBase.java    |    7 +-
 geode-book/config.yml                              |    1 +
 .../source/subnavs/geode-subnav.erb                |   10 +-
 .../geode/util/internal/TeeOutputStream.java       |    9 +
 .../geode/util/internal}/UncheckedUtils.java       |   19 +-
 .../geode/util/internal/GeodeConverterTest.java    |    1 +
 .../geode/util/internal/GeodeJsonMapperTest.java   |    1 +
 .../geode/util/internal/UncheckedUtilsTest.java    |   60 +
 .../internal/cli/CreateMappingCommandTest.java     |    5 +-
 .../jdbc/internal/xml/ElementTypeTest.java         |    3 +-
 .../xml/JdbcConnectorServiceXmlParserTest.java     |    3 +-
 .../geode/cache/ConnectionPoolDUnitTest.java       |   17 +-
 .../ClientServerRegisterInterestsDUnitTest.java    |    7 +-
 ...tServerHostNameVerificationDistributedTest.java |    3 +-
 .../internal/CustomSSLProviderDistributedTest.java |    3 +-
 .../query/dunit/CompactRangeIndexDUnitTest.java    |    6 +-
 .../query/dunit/CorruptedIndexIntegrationTest.java |   24 +-
 .../cache/query/dunit/HashIndexDUnitTest.java      |    4 +-
 ...MultiServerPartitionedRegionQueryDUnitTest.java |    7 +-
 .../geode/cache/query/dunit/PdxQueryDUnitTest.java |   23 +-
 ...PersistentRegionCompactRangeIndexDUnitTest.java |   44 +-
 .../dunit/QueryDataInconsistencyDUnitTest.java     |   27 +-
 .../cache/query/dunit/QueryIndexDUnitTest.java     |  122 +-
 .../query/dunit/QueryIndexUsingXMLDUnitTest.java   |   40 +-
 .../dunit/QueryUsingFunctionContextDUnitTest.java  |   28 +-
 .../cache/query/dunit/RemoteQueryDUnitTest.java    |    3 +-
 .../ResourceManagerWithQueryMonitorDUnitTest.java  |   24 +-
 .../query/dunit/SelectStarQueryDUnitTest.java      |   52 +-
 ...igurationServiceConstraintsDistributedTest.java |    6 +-
 .../AggregateFunctionsQueryDUnitTest.java          |  263 +-
 ...ntIndexOperationsOnOverflowRegionDUnitTest.java |   12 +-
 .../internal/index/CopyOnReadIndexDUnitTest.java   |   47 +-
 .../index/IndexTrackingQueryObserverDUnitTest.java |    5 +-
 .../InitializeIndexEntryDestroyQueryDUnitTest.java |    5 +-
 .../PRBasicMultiIndexCreationDUnitTest.java        |    4 +-
 .../query/partitioned/PRBasicQueryDUnitTest.java   |    3 +-
 .../partitioned/PRColocatedEquiJoinDUnitTest.java  |   26 +-
 .../query/partitioned/PRQueryDUnitHelper.java      |  327 ++-
 .../cache/query/partitioned/PRQueryDUnitTest.java  |   29 +-
 .../PRQueryRemoteNodeExceptionDUnitTest.java       |   11 +-
 .../apache/geode/cache30/CacheXml66DUnitTest.java  |   13 +-
 .../apache/geode/cache30/CacheXml70DUnitTest.java  |    9 +-
 .../apache/geode/cache30/CacheXml80DUnitTest.java  |   30 +-
 .../geode/cache30/DynamicRegionDUnitTest.java      |    7 +-
 .../geode/cache30/PutAllMultiVmDUnitTest.java      |   17 +-
 .../apache/geode/cache30/ReconnectDUnitTest.java   |    9 +-
 ...ReconnectWithClusterConfigurationDUnitTest.java |   33 +-
 .../geode/cache30/SearchAndLoadDUnitTest.java      |    5 +-
 .../org/apache/geode/cache30/TXOrderDUnitTest.java |   11 +-
 .../internal/CacheConfigDAODUnitTest.java          |    3 +-
 ...lusterDistributionManagerForAdminDUnitTest.java |    3 +-
 ...onCreateBeforeInitializationRegressionTest.java |    5 +-
 .../cache/ConcurrentDestroySubRegionDUnitTest.java |    9 +-
 .../cache/HAOverflowMemObjectSizerDUnitTest.java   |    7 +-
 .../geode/internal/cache/MapClearGIIDUnitTest.java |    3 +-
 .../cache/P2PDeltaPropagationDUnitTest.java        |   25 +-
 .../PRQueryWithIndexAndPdxDistributedTest.java     |   13 +-
 .../cache/ParallelDiskStoreRecoveryDUnitTest.java  |  309 +++
 .../cache/PartitionedRegionAPIDUnitTest.java       |    3 +-
 .../cache/PartitionedRegionDestroyDUnitTest.java   |    3 +-
 .../cache/PartitionedRegionSingleHopDUnitTest.java |   14 +-
 .../PrepareAndFinishBackupDistributedTest.java     |    3 +-
 .../control/RebalanceOperationDistributedTest.java |    9 +-
 ...istributedRegionFunctionExecutionDUnitTest.java |   59 +-
 .../execute/LocalDataSetIndexingDUnitTest.java     |   14 +-
 .../cache/execute/PRColocationDUnitTest.java       |  165 +-
 .../cache/execute/PRSetOperationJTADUnitTest.java  |   15 +-
 .../cache/execute/PRSetOperationTXDUnitTest.java   |    9 +-
 .../cache/execute/PRTransactionDUnitTest.java      |   45 +-
 .../cache/functions/LocalDataSetFunction.java      |   10 +-
 .../cache/ha/EventIdOptimizationDUnitTest.java     |   13 +-
 .../internal/cache/ha/HABugInPutDUnitTest.java     |    5 +-
 .../geode/internal/cache/ha/HAClearDUnitTest.java  |   33 +-
 .../internal/cache/ha/HAConflationDUnitTest.java   |   10 +-
 .../internal/cache/ha/HADuplicateDUnitTest.java    |    7 +-
 .../cache/ha/HAEventIdPropagationDUnitTest.java    |   21 +-
 .../geode/internal/cache/ha/HAExpiryDUnitTest.java |    6 +-
 .../geode/internal/cache/ha/HAGIIBugDUnitTest.java |   11 +-
 .../geode/internal/cache/ha/HARegionDUnitTest.java |   13 +-
 .../internal/cache/ha/HARegionQueueDUnitTest.java  |   15 +-
 .../geode/internal/cache/ha/PutAllDUnitTest.java   |    9 +-
 .../geode/internal/cache/ha/StatsBugDUnitTest.java |    3 +-
 .../cache/locks/TXLockServiceDUnitTest.java        |   14 +-
 ...PersistentPartitionedRegionDistributedTest.java |    2 +-
 .../fixed/FixedPartitioningTestBase.java           |   45 +-
 ...oningWithColocationAndPersistenceDUnitTest.java |   12 +-
 .../sockets/CacheServerTransactionsDUnitTest.java  |   19 +-
 .../tier/sockets/ClearPropagationDUnitTest.java    |   21 +-
 .../tier/sockets/ClientConflationDUnitTest.java    |   17 +-
 .../sockets/ClientInterestNotifyDUnitTest.java     |   25 +-
 .../tier/sockets/ClientServerMiscDUnitTest.java    |    3 +-
 .../ClientWithInterestFailoverDistributedTest.java |    9 +-
 .../cache/tier/sockets/ConflationDUnitTest.java    |   47 +-
 .../sockets/DestroyEntryPropagationDUnitTest.java  |   17 +-
 .../sockets/DurableResponseMatrixDUnitTest.java    |   63 +-
 .../cache/tier/sockets/HABug36738DUnitTest.java    |    5 +-
 .../cache/tier/sockets/HAInterestTestCase.java     |   16 +-
 .../cache/tier/sockets/InterestListDUnitTest.java  |   36 +-
 .../sockets/InterestRegrListenerDUnitTest.java     |    4 +-
 .../sockets/InterestResultPolicyDUnitTest.java     |    9 +-
 .../tier/sockets/NewRegionAttributesDUnitTest.java |   17 +-
 .../sockets/RedundancyLevelPart1DUnitTest.java     |    5 +-
 .../tier/sockets/RedundancyLevelTestBase.java      |   13 +-
 ...isterInterestBeforeRegionCreationDUnitTest.java |    4 +-
 .../sockets/RegisterInterestKeysDUnitTest.java     |    5 +-
 .../tier/sockets/ReliableMessagingDUnitTest.java   |    7 +-
 .../tier/sockets/UpdatePropagationDUnitTest.java   |   11 +-
 ...ifyUpdatesFromNonInterestEndPointDUnitTest.java |   11 +-
 .../cache/tx/SetOperationJTADistributedTest.java   |    7 +-
 .../asyncqueue/AsyncEventQueueStatsDUnitTest.java  |    3 +-
 .../wan/misc/CommonAsyncEventQueueDUnitTest.java   |    3 +-
 .../jta/dunit/TxnManagerMultiThreadDUnitTest.java  |    5 +-
 .../management/ClientHealthStatsDUnitTest.java     |    7 +-
 ...stemMXBeanWithNotificationsDistributedTest.java |    4 +-
 .../management/JMXMBeanReconnectDUnitTest.java     |    7 +-
 .../MemberMXBeanAttributesDistributedTest.java     |   13 +-
 .../geode/management/QueryDataDUnitTest.java       |   53 +-
 .../geode/management/QueryPdxDataDUnitTest.java    |    4 +-
 .../internal/JMXMBeanFederationDUnitTest.java      |    3 +-
 .../ClusterConfigLocatorRestartDUnitTest.java      |    3 +-
 .../ClusterConfigWithCallbacksDUnitTest.java       |    3 +-
 .../internal/pulse/TestSubscriptionsDUnitTest.java |    5 +-
 .../security/MultiUserAuthenticationDUnitTest.java |    5 +-
 .../internal/util/ManagementUtilsDUnitTest.java    |   17 +-
 .../NoShowValue1PostProcessorDUnitTest.java        |    3 +-
 .../PDXGfshPostProcessorOnRemoteServerTest.java    |    3 +-
 .../geode/security/PDXPostProcessorDUnitTest.java  |    6 +-
 .../geode/security/PostProcessorDUnitTest.java     |    3 +-
 .../query/PdxQuerySecurityDistributedTest.java     |   13 +-
 ...QuerySecurityAllowedQueriesDistributedTest.java |   76 +-
 ...erySecurityForbiddenQueriesDistributedTest.java |   86 +-
 .../java/org/apache/geode/TXJUnitTest.java         |    5 +-
 .../org/apache/geode/cache/ProxyJUnitTest.java     |    5 +-
 .../cache/client/ClientCacheFactoryJUnitTest.java  |   10 +-
 .../cache/client/ClientRegionFactoryJUnitTest.java |    3 +-
 .../cache/query/JoinQueriesIntegrationTest.java    |   38 +-
 .../cache/query/LocalQueryServiceJUnitTest.java    |    7 +-
 .../geode/cache/query/PdxStringQueryJUnitTest.java |  199 +-
 .../apache/geode/cache/query/QueryJUnitTest.java   |  103 +-
 .../geode/cache/query/QueryServiceJUnitTest.java   |   90 +-
 .../cache/query/QueryServiceRegressionTest.java    |   88 +-
 .../QueryWithBucketParameterIntegrationTest.java   |    3 +-
 .../apache/geode/cache/query/RegionJUnitTest.java  |   27 +-
 .../geode/cache/query/TypedIteratorJUnitTest.java  |   15 +-
 .../functional/ComparisonOperatorsJUnitTest.java   |   13 +-
 .../cache/query/functional/ConstantsJUnitTest.java |   13 +-
 .../functional/CustomerOptimizationsJUnitTest.java |  202 +-
 .../DistinctAndNonDistinctQueryJUnitTest.java      |   16 +-
 ...tinctResultsWithDupValuesInRegionJUnitTest.java |   21 +-
 .../cache/query/functional/FunctionJUnitTest.java  |   17 +-
 .../query/functional/INOperatorJUnitTest.java      |   40 +-
 .../query/functional/IUM6Bug32345ReJUnitTest.java  |   12 +-
 .../geode/cache/query/functional/IUMJUnitTest.java |   11 +-
 .../functional/IUMRCompositeIteratorJUnitTest.java |   11 +-
 .../IUMRMultiIndexesMultiRegionJUnitTest.java      |  196 +-
 .../functional/IUMRShuffleIteratorsJUnitTest.java  |   56 +-
 .../functional/IUMRSingleRegionJUnitTest.java      |  108 +-
 ...IndependentOperandsInWhereClause2JUnitTest.java |  125 +-
 .../functional/IndexCreationDeadLockJUnitTest.java |    5 +-
 .../query/functional/IndexCreationJUnitTest.java   |  229 +-
 .../IndexMaintenanceAsynchJUnitTest.java           |    7 +-
 .../query/functional/IndexOnEntrySetJUnitTest.java |   14 +-
 .../functional/IndexPrimaryKeyUsageJUnitTest.java  |   55 +-
 .../IndexUsageInNestedQueryJUnitTest.java          |   35 +-
 ...IndexUsageInNestedQueryWithParamsJUnitTest.java |   11 +-
 .../IndexUsageWithAliasAsProjAtrbtJUnitTest.java   |   16 +-
 .../IndexUseMultFrmSnglCondJUnitTest.java          |   17 +-
 .../IndexWithSngleFrmAndMultCondQryJUnitTest.java  |  100 +-
 .../functional/IteratorTypeDefEmpJUnitTest.java    |    4 +-
 .../query/functional/IteratorTypeDefJUnitTest.java |   24 +-
 .../functional/IumMultConditionJUnitTest.java      |   12 +-
 .../query/functional/LikePredicateJUnitTest.java   |  474 ++--
 .../query/functional/LimitClauseJUnitTest.java     |  226 +-
 .../cache/query/functional/MiscJUnitTest.java      |  111 +-
 .../functional/MultiRegionIndexUsageJUnitTest.java |  125 +-
 .../query/functional/MultipleRegionsJUnitTest.java |   22 +-
 .../functional/NegativeNumberQueriesJUnitTest.java |   11 +-
 .../query/functional/NestedQueryJUnitTest.java     |  136 +-
 .../NonDistinctOrderByPartitionedJUnitTest.java    |  151 +-
 .../NonDistinctOrderByReplicatedJUnitTest.java     |   36 +-
 .../query/functional/NumericQueryJUnitTest.java    |   45 +-
 .../functional/OrderByReplicatedJUnitTest.java     |  399 +--
 .../functional/ParameterBindingJUnitTest.java      |   19 +-
 .../functional/QRegionInterfaceJUnitTest.java      |   34 +-
 .../QueryREUpdateInProgressJUnitTest.java          |   81 +-
 .../query/functional/QueryUndefinedJUnitTest.java  |   36 +-
 .../functional/ReservedKeywordsJUnitTest.java      |    7 +-
 .../ResultsDataSerializabilityJUnitTest.java       |    3 +-
 .../query/functional/SelectToDateJUnitTest.java    |   31 +-
 .../functional/StructMemberAccessJUnitTest.java    |   59 +-
 .../TestNewFunctionSSorRSIntegrationTest.java      |   10 +-
 .../ArithmeticOperationsIntegrationTest.java       |   55 +-
 .../CompiledGroupBySelectIntegrationTest.java      |  205 +-
 .../CompiledJunctionInternalsJUnitTest.java        |  102 +-
 .../query/internal/CopyOnReadQueryJUnitTest.java   |   10 +-
 .../DefaultQuerySecurityIntegrationTest.java       |   21 +-
 .../internal/ExecutionContextIntegrationTest.java  |   30 +-
 .../internal/GroupJunctionIntegrationTest.java     |   16 +-
 .../query/internal/IndexManagerJUnitTest.java      |   27 +-
 .../query/internal/OrderByComparatorJUnitTest.java |   11 +-
 .../internal/ProjectionAttributeJUnitTest.java     |   78 +-
 .../QueryFromClauseCanonicalizationJUnitTest.java  |   29 +-
 .../internal/QueryMonitorIntegrationTest.java      |    4 +-
 .../query/internal/QueryObserverCallbacksTest.java |  114 +-
 .../cache/query/internal/QueryTraceJUnitTest.java  |   33 +-
 .../cache/query/internal/QueryUtilsJUnitTest.java  |    8 +-
 .../internal/aggregate/AvgIntegrationTest.java     |   96 +-
 .../internal/aggregate/CountIntegrationTest.java   |  118 +-
 .../internal/aggregate/MaxIntegrationTest.java     |  148 +-
 .../internal/aggregate/MinIntegrationTest.java     |  148 +-
 .../internal/aggregate/SumIntegrationTest.java     |   98 +-
 .../AbstractIndexMaintenanceIntegrationTest.java   |   11 +-
 .../index/AsynchIndexMaintenanceJUnitTest.java     |   13 +-
 .../index/CompactRangeIndexIndexMapJUnitTest.java  |   35 +-
 .../internal/index/CompactRangeIndexJUnitTest.java |   61 +-
 .../CompactRangeIndexQueryIntegrationTest.java     |   19 +-
 .../index/DeclarativeIndexCreationJUnitTest.java   |    9 +-
 .../internal/index/EquiJoinIntegrationTest.java    |  143 +-
 .../index/HashIndexMaintenanceIntegrationTest.java |   11 +-
 .../index/HashIndexQueryIntegrationTest.java       |  241 +-
 .../index/IndexCreationInternalsJUnitTest.java     |    5 +-
 .../query/internal/index/IndexHintJUnitTest.java   |  131 +-
 .../cache/query/internal/index/IndexJUnitTest.java |    6 +-
 .../internal/index/IndexMaintainceJUnitTest.java   |  105 +-
 .../internal/index/IndexMaintenanceJUnitTest.java  |   80 +-
 .../internal/index/IndexStatisticsJUnitTest.java   |   45 +-
 .../index/IndexTrackingQueryObserverJUnitTest.java |    9 +-
 .../query/internal/index/IndexUseJUnitTest.java    |  369 +--
 .../IndexedMergeEquiJoinScenariosJUnitTest.java    |  351 ++-
 .../internal/index/MapIndexStoreJUnitTest.java     |    4 +-
 .../index/MapRangeIndexMaintenanceJUnitTest.java   |  250 +-
 .../NewDeclarativeIndexCreationJUnitTest.java      |   15 +-
 .../PartitionedRegionEquiJoinIntegrationTest.java  |    5 +-
 .../index/PdxCopyOnReadQueryJUnitTest.java         |    7 +-
 .../internal/index/RangeIndexAPIJUnitTest.java     |   57 +-
 .../query/partitioned/PRColocatedEquiJoinTest.java |   11 +-
 .../partitioned/PRIndexStatisticsJUnitTest.java    |   41 +-
 .../cache/query/partitioned/PRQueryJUnitTest.java  |   11 +-
 .../partitioned/PRQueryNumThreadsJUnitTest.java    |    8 +-
 .../query/transaction/QueryAndJtaJUnitTest.java    |   75 +-
 .../RestrictUseOfInetAddressJUnitTest.java         |    1 +
 .../LoadClusterConfigFromDirIntegrationTest.java   |   73 +
 .../geode/internal/ClassPathLoaderJUnitTest.java   |  239 +-
 ...ionCreateNotBeforeRegionInitRegressionTest.java |    4 +-
 ...tMessagesRegionCreationAndDestroyJUnitTest.java |    8 +-
 .../geode/internal/cache/ColocatedPRJUnitTest.java |    3 +-
 .../internal/cache/DiskRegCacheXmlJUnitTest.java   |   34 +-
 .../LIFOEvictionAlgoEnabledRegionJUnitTest.java    |   15 +-
 ...FOEvictionAlgoMemoryEnabledRegionJUnitTest.java |   15 +-
 ...rtitionedRegionSerializableObjectJUnitTest.java |    5 +-
 ...itionedRegionSingleNodeOperationsJUnitTest.java |    3 +-
 .../backup/BackupFileCopierIntegrationTest.java    |    3 +-
 .../FunctionExecutionOnLonerRegressionTest.java    |   27 +-
 .../ModifyColocationIntegrationTest.java           |   11 +-
 .../tier/sockets/RedundancyLevelJUnitTest.java     |    3 +-
 ...elGatewaySenderFlushedCoordinatorJUnitTest.java |    2 +-
 .../geode/internal/jta/DataSourceJTAJUnitTest.java |    9 +-
 .../internal/jta/SetOperationJTAJUnitTest.java     |    5 +-
 .../internal/jta/functional/CacheJUnitTest.java    |    2 +-
 .../internal/offheap/OffHeapIndexJUnitTest.java    |   11 +-
 .../management/DataQueryEngineIntegrationTest.java |    9 +-
 .../bean/stats/RegionStatsJUnitTest.java           |    4 +-
 .../internal/beans/RegionMBeanAttributesTest.java  |    4 +-
 .../security/GfshCommandsPostProcessorTest.java    |    3 +-
 .../apache/geode/pdx/PdxSerializableJUnitTest.java |    9 +-
 .../ClientCacheFactoryJUnitTest_single_pool.xml    |    2 +-
 .../codeAnalysis/sanctionedDataSerializables.txt   |    8 +-
 .../internal/ra/spi/JCAManagedConnection.java      |   33 +-
 .../geode/cache/RangeQueryWithIndexBenchmark.java  |    7 +-
 .../geode/admin/internal/InetAddressUtils.java     |    9 +
 .../admin/internal/SystemMemberRegionImpl.java     |    4 +-
 .../jmx/internal/MemberInfoWithStatsMBean.java     |    3 +-
 .../main/java/org/apache/geode/cache/Region.java   |   68 +-
 .../internal/ParallelAsyncEventQueueImpl.java      |   12 +-
 .../internal/SerialAsyncEventQueueImpl.java        |   19 +-
 .../client/internal/ClientMetadataService.java     |    4 +-
 .../cache/client/proxy/ProxySocketFactories.java   |    2 +-
 ...cketFactory.java => SniProxySocketFactory.java} |    6 +-
 .../geode/cache/configuration/CacheConfig.java     |   13 +
 .../org/apache/geode/cache/wan/GatewaySender.java  |   34 +
 .../geode/cache/wan/GatewaySenderFactory.java      |   13 +
 .../geode/distributed/ConfigurationProperties.java |   50 +-
 .../internal/AbstractDistributionConfig.java       |   11 +-
 .../distributed/internal/DistributionConfig.java   |   60 +-
 .../internal/DistributionConfigImpl.java           |   34 +-
 .../InternalConfigurationPersistenceService.java   |   16 +-
 .../distributed/internal/InternalLocator.java      |    2 +-
 .../geode/internal/InternalDataSerializer.java     |    5 +
 .../org/apache/geode/internal/admin/SSLConfig.java |    2 +-
 .../geode/internal/cache/BucketRegionQueue.java    |   31 +
 .../geode/internal/cache/ColocationHelper.java     |    3 +-
 .../geode/internal/cache/DiskStoreFactoryImpl.java |    7 +-
 .../geode/internal/cache/DistributedRegion.java    |    4 +-
 .../geode/internal/cache/GemFireCacheImpl.java     |  117 +-
 .../apache/geode/internal/cache/InternalCache.java |    4 +
 .../cache/InternalCacheForClientAccess.java        |   16 +-
 .../geode/internal/cache/InternalRegion.java       |    3 +
 .../apache/geode/internal/cache/LocalRegion.java   |   35 +-
 .../geode/internal/cache/LocalRegionDataView.java  |    5 +-
 .../geode/internal/cache/PartitionedRegion.java    |   26 +-
 .../internal/cache/PartitionedRegionHelper.java    |   16 +-
 .../geode/internal/cache/ProxyBucketRegion.java    |    5 +-
 .../geode/internal/cache/RegionNameValidation.java |    7 +-
 .../geode/internal/cache/TXCommitMessage.java      |   29 +-
 .../cache/TXLastEventInTransactionUtils.java       |  120 +
 .../org/apache/geode/internal/cache/TXState.java   |   24 +-
 .../util/TypedFunctionService.java}                |   20 +-
 .../cache/tier/sockets/CacheClientNotifier.java    |    4 +-
 .../tier/sockets/CacheClientProxyFactory.java      |    4 +-
 .../tier/sockets/ClientProxyMembershipID.java      |    5 +-
 .../internal/cache/wan/AbstractGatewaySender.java  |   18 +-
 .../wan/AbstractGatewaySenderEventProcessor.java   |   37 +-
 .../cache/wan/GatewaySenderAttributes.java         |    6 +
 .../internal/cache/wan/GatewaySenderEventImpl.java |   74 +-
 ...currentParallelGatewaySenderEventProcessor.java |   19 +-
 .../ConcurrentParallelGatewaySenderQueue.java      |    6 +
 .../ParallelGatewaySenderEventProcessor.java       |   20 +-
 .../wan/parallel/ParallelGatewaySenderQueue.java   |  252 +-
 .../wan/parallel/ParallelQueueRemovalMessage.java  |    4 +-
 ...oncurrentSerialGatewaySenderEventProcessor.java |   24 +-
 .../serial/SerialGatewaySenderEventProcessor.java  |   19 +-
 .../cache/wan/serial/SerialGatewaySenderQueue.java |  240 +-
 .../internal/cache/xmlcache/CacheCreation.java     |   41 +-
 .../geode/internal/cache/xmlcache/CacheXml.java    |    2 +
 .../internal/cache/xmlcache/CacheXmlGenerator.java |   10 +
 .../internal/cache/xmlcache/CacheXmlParser.java    |   10 +
 .../xmlcache/ParallelAsyncEventQueueCreation.java  |    3 +
 .../xmlcache/ParallelGatewaySenderCreation.java    |    3 +
 .../internal/cache/xmlcache/RegionCreation.java    |    4 +-
 .../xmlcache/SerialAsyncEventQueueCreation.java    |    3 +
 .../xmlcache/SerialGatewaySenderCreation.java      |    3 +
 .../geode/internal/io/CompositeOutputStream.java   |    8 +
 .../geode/internal/lang/SystemPropertyHelper.java  |    6 +
 .../internal => internal/net}/SSLUtil.java         |   67 +-
 .../apache/geode/internal/net/SocketCreator.java   |   34 +-
 .../sequencelog/io/GemfireLogConverter.java        |   10 +-
 .../org/apache/geode/internal/tcp/Connection.java  |   20 +-
 .../geode/logging/internal/LoggingSession.java     |   16 +-
 .../geode/management/GatewaySenderMXBean.java      |   11 +
 .../internal/api/GeodeConnectionConfig.java        |    2 +-
 .../api/LocatorClusterManagementService.java       |    4 +-
 .../management/internal/beans/DataQueryEngine.java |    4 +-
 .../internal/beans/GatewaySenderMBean.java         |   10 +
 .../internal/beans/GatewaySenderMBeanBridge.java   |    9 +
 .../functions/CacheRealizationFunction.java        |   47 +-
 .../geode/management/internal/i18n/CliStrings.java |   25 +-
 .../internal/operation/OperationManager.java       |   17 +-
 .../internal/operation/OperationPerformer.java     |   22 +-
 .../operation/RebalanceOperationPerformer.java     |   15 +-
 .../management/internal/util/ManagementUtils.java  |    6 +-
 .../geode/management/internal/util/RegionPath.java |   16 +-
 .../apache/geode/security/ResourcePermission.java  |    5 +-
 .../geode.apache.org/schema/cache/cache-1.0.xsd    |    1 +
 .../BaseLineAndCompareQueryPerfJUnitTest.java      |   96 +-
 .../internal/ClusterAlertMessagingTest.java        |    6 +-
 .../internal/ParallelAsyncEventQueueImplTest.java  |   97 +
 .../internal/SerialAsyncEventQueueImplTest.java    |   31 +-
 .../geode/cache/configuration/CacheConfigTest.java |   13 +-
 .../org/apache/geode/cache/query/PerfQuery.java    |   17 +-
 .../geode/cache/query/internal/QCompilerTest.java  |   73 +-
 .../internal/index/CompactRangeIndexTest.java      |    8 +-
 .../cache/query/internal/parse/OQLParserTest.java  |    7 +-
 .../internal/DistributionConfigJUnitTest.java      |    4 +-
 .../geode/internal/cache/BucketAdvisorTest.java    |   28 +-
 .../cache/BucketPersistenceAdvisorTest.java        |    3 +-
 .../internal/cache/BucketRegionQueueJUnitTest.java |   81 +-
 .../geode/internal/cache/ColocationHelperTest.java |    5 +-
 .../geode/internal/cache/GemFireCacheImplTest.java |   42 +
 .../internal/cache/PRHARedundancyProviderTest.java |    3 +-
 .../cache/PartitionedRegionHelperJUnitTest.java    |   12 +-
 .../cache/TXLastEventInTransactionUtilsTest.java   |  196 ++
 .../RestoreRedundancyOperationImplTest.java        |    7 +-
 .../cache/execute/LocalDataSetFunction.java        |   10 +-
 .../SingleThreadColocationLoggerTest.java          |   22 +-
 .../persistence/PersistenceAdvisorImplTest.java    |    5 +-
 ...entParallelGatewaySenderEventProcessorTest.java |    4 +-
 ...rallelGatewaySenderEventProcessorJUnitTest.java |   11 +-
 .../ParallelGatewaySenderEventProcessorTest.java   |    5 +-
 .../wan/parallel/ParallelGatewaySenderHelper.java  |   10 +-
 .../ParallelGatewaySenderQueueJUnitTest.java       |  192 +-
 .../ParallelQueueRemovalMessageJUnitTest.java      |    4 +-
 ...SerialGatewaySenderEventProcessorJUnitTest.java |    2 +-
 ...SerialGatewaySenderEventProcessorJUnitTest.java |   13 +-
 .../serial/SerialGatewaySenderQueueJUnitTest.java  |  251 ++
 .../TestSerialGatewaySenderEventProcessor.java     |    6 +-
 .../io/CompositeOutputStreamJUnitTest.java         |   55 +-
 .../internal/lang/SystemPropertyHelperTest.java    |   51 +
 .../org/apache/geode/internal/net/SSLUtilTest.java |   86 +
 .../apache/geode/internal/tcp/TCPConduitTest.java  |    4 +-
 .../geode/logging/internal/LoggingSessionTest.java |   22 +
 .../beans/GatewaySenderMBeanBridgeTest.java        |   94 +
 .../internal/beans/GatewaySenderMBeanTest.java     |   41 +-
 .../QueryDataFunctionApplyLimitClauseTest.java     |    8 +-
 .../mutators/IndexConfigManagerTest.java           |    5 +-
 .../configuration/realizers/IndexRealizerTest.java |    9 +-
 .../realizers/RegionConfigRealizerTest.java        |    7 +-
 .../functions/CacheRealizationFunctionTest.java    |  129 +
 .../internal/operation/OperationManagerTest.java   |   26 +-
 .../operation/RebalanceOperationPerformerTest.java |   26 +-
 .../internal/security/ResourcePermissionTest.java  |    5 +-
 .../RollingUpgrade2DUnitTestBase.java              |    3 +-
 .../rollingupgrade/RollingUpgradeTracePRQuery.java |    4 +-
 ...ientStatisticsPublicationSecurityDUnitTest.java |    3 +-
 .../geode/cache/query/cq/CQDistributedTest.java    |   16 +-
 .../cq/ContinuousQueryValidationDUnitTest.java     |   47 +-
 .../cache/query/cq/dunit/CqDataDUnitTest.java      |   25 +-
 .../query/cq/dunit/CqDataUsingPoolDUnitTest.java   |  123 +-
 .../cache/query/cq/dunit/CqQueryDUnitTest.java     |  111 +-
 .../query/cq/dunit/CqQueryUsingPoolDUnitTest.java  |   67 +-
 .../cq/dunit/CqResultSetUsingPoolDUnitTest.java    |   86 +-
 ...esultSetUsingPoolOptimizedExecuteDUnitTest.java |   13 +-
 .../cache/query/cq/dunit/CqStateDUnitTest.java     |    3 +-
 .../cache/query/cq/dunit/CqStatsDUnitTest.java     |   13 +-
 .../query/cq/dunit/CqStatsUsingPoolDUnitTest.java  |   13 +-
 .../DestroyPartitionedRegionMessageDUnitTest.java  |    4 +-
 ...nvalidatePartitionedRegionMessageDUnitTest.java |    4 +-
 .../dunit/PartitionedRegionCqQueryDUnitTest.java   |   37 +-
 .../query/cq/dunit/PrCqUsingPoolDUnitTest.java     |   39 +-
 ...tyExecutionContextTamperingDistributedTest.java |    4 +-
 .../query/dunit/QueryIndexUpdateRIDUnitTest.java   |   34 +-
 .../cache/query/dunit/QueryMonitorDUnitTest.java   |  151 +-
 ...igurationServiceConstraintsDistributedTest.java |    3 +-
 .../cache/snapshot/ClientSnapshotDUnitTest.java    |    7 +-
 .../cache/PRDeltaPropagationDUnitTest.java         |    3 +-
 .../cache/PutAllClientServerDistributedTest.java   |  214 +-
 .../internal/cache/ha/CQListGIIDUnitTest.java      |   29 +-
 .../internal/cache/ha/HADispatcherDUnitTest.java   |    9 +-
 .../tier/sockets/ClientToServerDeltaDUnitTest.java |    9 +-
 .../sockets/DeltaPropagationWithCQDUnitTest.java   |    3 +-
 ...ltaToRegionRelationCQRegistrationDUnitTest.java |   10 +-
 .../tier/sockets/DurableClientCQDUnitTest.java     |  107 +-
 .../sockets/DurableClientHAQueuedDUnitTest.java    |  151 +-
 .../tier/sockets/DurableClientSimpleDUnitTest.java |   16 +-
 .../management/CacheServerManagementDUnitTest.java |    4 +-
 .../AlterQueryServiceCommandDistributedTest.java   |    4 +-
 .../commands/DescribeClientCommandDUnitTest.java   |    9 +-
 .../commands/DurableClientCommandsDUnitTest.java   |    9 +-
 .../security/CQPDXPostProcessorDUnitTest.java      |    3 +-
 .../geode/security/CQPostProcessorDunitTest.java   |    5 +-
 .../geode/security/ClientCQAuthDUnitTest.java      |    3 +-
 .../geode/security/ClientQueryAuthDUnitTest.java   |    3 +-
 .../geode/security/MultiUserAPIDUnitTest.java      |    5 +-
 .../CqSecurityAllowedUsersDistributedTest.java     |   21 +-
 .../CqSecurityForbiddenUsersDistributedTest.java   |   13 +-
 .../cache/query/cq/internal/ServerCQImplTest.java  |    4 +-
 .../tier/sockets/ClientServerMiscBCDUnitTest.java  |    3 +-
 .../running/cluster-management-service.html.md.erb |  114 +-
 geode-docs/images/redis_api_for_geode.png          |  Bin 0 -> 62103 bytes
 ...timize_availability_and_performance.html.md.erb |    5 +
 .../managing/security/implementing_ssl.html.md.erb |    8 +-
 geode-docs/reference/statistics_list.html.md.erb   |    2 +-
 geode-docs/reference/topics/cache_xml.html.md.erb  |    7 +
 .../reference/topics/client-cache.html.md.erb      |    2 +-
 .../topics/gemfire_properties.html.md.erb          |   26 +
 geode-docs/tools_modules/book_intro.html.md.erb    |    4 +-
 .../gfsh/command-pages/create.html.md.erb          |   21 +-
 .../gfsh/command-pages/query.html.md.erb           |   13 +-
 .../gfsh/command-pages/start.html.md.erb           |   15 +-
 geode-docs/tools_modules/redis_adapter.html.md.erb |   90 -
 .../tools_modules/redis_api_for_geode.html.md.erb  |   89 +
 .../setting_up_a_client_server_system.html.md.erb  |    2 +-
 .../setting_up_a_multisite_system.html.md.erb      |   33 +
 .../multisite_overview.html.md.erb                 |    7 +
 .../apache/geode/cache/query/QueryTestUtils.java   | 2575 +++++++++++++-------
 .../OrderByPartitionedJUnitTestBase.java           |  367 +--
 .../functional/OrderByTestImplementation.java      |  300 ++-
 .../geode/cache30/MultiVMRegionTestCase.java       |    3 +-
 .../org/apache/geode/cache30/RegionTestCase.java   |   20 +-
 .../cache/wan/AsyncEventQueueTestBase.java         |   18 +-
 .../commands/FunctionCommandsDUnitTestBase.java    |    7 +-
 .../commands/GemfireDataCommandsDUnitTestBase.java |   16 +-
 .../commands/IndexCommandsIntegrationTestBase.java |    9 +-
 .../commands/ListIndexCommandDUnitTestBase.java    |    4 +-
 ...tedQueryClassCastExceptionFailureDUnitTest.java |   12 +-
 .../cli/commands/QueryCommandDUnitTestBase.java    |   42 +
 .../commands/QueryCommandIntegrationTestBase.java  |   39 +-
 .../RegionMembershipMBeanDUnitTestBase.java        |   21 +-
 .../security/GfshCommandsSecurityTestBase.java     |    3 +-
 .../generator/XmlAuthzCredentialGenerator.java     |    4 +-
 .../AbstractQuerySecurityDistributedTest.java      |    3 +-
 .../geode/security/templates/XmlAuthorization.java |   10 +-
 .../test/dunit/rules/SharedErrorCollector.java     |   44 +-
 .../driver/PostProcessingIntegrationTest.java      |    4 +-
 .../driver/QueryServiceIntegrationTest.java        |    4 +-
 .../apache/geode/experimental/driver/SSLTest.java  |    5 +-
 .../management/internal/cli/CliUtilDUnitTest.java  |    7 +-
 .../cli/commands/AlterRegionCommandDUnitTest.java  |    9 +-
 .../cli/commands/CreateIndexCommandDUnitTest.java  |   19 +-
 .../cli/commands/CreateRegionCommandDUnitTest.java |  122 +-
 ...egionCommandPersistsConfigurationDUnitTest.java |    6 +-
 ...eRegionCommandWithNoClusterConfigDUnitTest.java |    3 +-
 .../commands/CreateRegionSecurityDUnitTest.java    |    7 +-
 .../commands/DestroyIndexCommandsDUnitTest.java    |    3 +-
 .../commands/DestroyRegionCommandDUnitTest.java    |   22 +-
 .../cli/commands/DiskStoreCommandsDUnitTest.java   |    3 +-
 .../commands/ExecuteFunctionCommandDUnitTest.java  |   30 +-
 .../GfshHostNameVerificationDistributedTest.java   |   15 +-
 .../cli/commands/LocateEntryDUnitTest.java         |   15 +-
 .../cli/commands/RebalanceCommandDUnitTest.java    |    2 +-
 .../commands/RebalanceMembersColocationTest.java   |    2 +-
 .../cli/commands/RemoveCommandDUnitTest.java       |    2 +-
 .../cli/commands/RepeatedRebalanceDUnitTest.java   |   86 +-
 .../cli/commands/ShowMetricsDUnitTest.java         |    3 +-
 .../internal/cli/GfshParserConverterTest.java      |    8 +-
 .../internal/cli/GfshParserParsingTest.java        |   25 +-
 .../AlterRegionCommandIntegrationTest.java         |   20 +-
 .../CreateRegionCommandIntegrationTest.java        |  279 ++-
 .../cli/commands/ExportDataIntegrationTest.java    |    5 +-
 .../cli/commands/GetCommandIntegrationTest.java    |    4 +-
 .../cli/commands/ImportDataIntegrationTest.java    |    5 +-
 .../cli/commands/PutCommandIntegrationTest.java    |   24 +-
 .../ShowMetricsCommandIntegrationTest.java         |    5 +-
 .../cli/domain/IndexDetailsIntegrationTest.java    |    3 +-
 .../DataCommandFunctionWithPDXJUnitTest.java       |   12 +-
 .../internal/cli/commands/ConnectCommand.java      |    2 +-
 .../cli/commands/CreateGatewaySenderCommand.java   |   20 +-
 .../internal/cli/commands/CreateRegionCommand.java |    6 +-
 .../commands/DescribeOfflineDiskStoreCommand.java  |    5 +-
 .../internal/cli/commands/QueryCommand.java        |   33 +-
 .../internal/cli/commands/RebalanceCommand.java    |    2 +-
 .../cli/commands/StartGatewaySenderCommand.java    |   13 +-
 .../internal/cli/commands/StartServerCommand.java  |   11 +
 .../cli/converters/RegionPathConverter.java        |    9 +-
 .../cli/functions/DataCommandFunction.java         |    4 +-
 .../cli/functions/GatewaySenderCreateFunction.java |    5 +
 .../cli/functions/GatewaySenderFunctionArgs.java   |    6 +
 .../cli/functions/RegionDestroyFunction.java       |    4 +-
 .../sanctioned-geode-gfsh-serializables.txt        |    3 +-
 .../cli/CommandSeparatorEscapeJUnitTest.java       |   35 +-
 .../internal/cli/GfshParserJUnitTest.java          |   11 +-
 .../cli/commands/AlterRegionCommandTest.java       |   15 +-
 .../commands/CreateGatewaySenderCommandTest.java   |   25 +-
 .../cli/commands/CreateIndexCommandTest.java       |   26 +-
 .../cli/commands/CreateRegionCommandTest.java      |    5 +-
 .../cli/commands/DescribeRegionJUnitTest.java      |    3 +-
 .../cli/commands/DestroyRegionCommandTest.java     |    7 +-
 .../cli/commands/ListIndexCommandJUnitTest.java    |    3 +-
 .../internal/cli/commands/QueryCommandTest.java    |   76 +
 .../converters/RegionPathConverterJUnitTest.java   |   28 +-
 .../CreateDefinedIndexesFunctionTest.java          |    7 +-
 .../DescribeDiskStoreFunctionJUnitTest.java        |   61 +-
 .../cli/functions/GetRegionsFunctionTest.java      |    3 +-
 .../cli/functions/ListIndexFunctionJUnitTest.java  |   20 +-
 .../functions/RegionCreateFunctionJUnitTest.java   |    5 +-
 .../ShowMissingDiskStoresFunctionTest.java         |   13 +-
 .../cli/functions/UserFunctionExecutionTest.java   |   10 +-
 .../internal/cli/util/HyphenFormatterTest.java     |   13 +-
 .../internal/cli/util/RegionPathTest.java          |   20 +-
 .../geode/internal/cache/InternalHttpService.java  |    2 +-
 .../NonDistinctOrderByTestImplementation.java      |  520 ++--
 .../management/internal/security/TestCommand.java  |   10 +-
 .../java/org/apache/geode/test/fake/Fakes.java     |    3 +
 .../rules/accessible/AccessibleErrorCollector.java |   64 +
 .../test/junit/rules/ExecutorServiceRuleTest.java  |   26 +
 .../cache/lucene/test/LuceneTestUtilities.java     |   34 +-
 .../cli/DestroyLuceneIndexCommandsDUnitTest.java   |   21 +-
 .../cache/lucene/LuceneQueriesIntegrationTest.java |    4 +-
 .../cli/LuceneIndexCommandsIntegrationTest.java    |   12 +-
 .../LuceneIndexXmlParserIntegrationJUnitTest.java  |    9 +-
 .../CreateLuceneCommandParametersValidator.java    |    6 +-
 .../lucene/internal/DestroyLuceneIndexMessage.java |    5 +-
 .../internal/LuceneIndexForPartitionedRegion.java  |    4 +-
 .../internal/management/LuceneServiceBridge.java   |    7 +-
 .../IndexRepositoryImplPerformanceTest.java        |    8 +-
 .../PartitionedRepositoryManagerJUnitTest.java     |    5 +-
 .../RawLuceneRepositoryManagerJUnitTest.java       |    5 +-
 .../internal/ValidateCommandParametersTest.java    |   15 +-
 .../internal/cli/LuceneIndexCommandsJUnitTest.java |   33 +-
 .../LuceneCreateIndexFunctionJUnitTest.java        |   14 +-
 .../LuceneDescribeIndexFunctionJUnitTest.java      |    5 +-
 .../LuceneDestroyIndexFunctionJUnitTest.java       |   19 +-
 .../LuceneListIndexFunctionJUnitTest.java          |    3 +-
 .../distributed/LuceneQueryFunctionJUnitTest.java  |    3 +-
 .../WaitUntilFlushedFunctionJUnitTest.java         |    3 +-
 .../xml/LuceneIndexXmlParserJUnitTest.java         |    3 +-
 .../geode/management/configuration/Index.java      |    5 +-
 .../geode/management/configuration/Region.java     |    7 +-
 .../geode/management/configuration/IndexTest.java  |   15 +-
 .../geode/management/configuration/RegionTest.java |    9 +-
 .../ClientClusterManagementServiceTest.java        |    4 +-
 .../src/test/script/update-management-wiki.sh      |   18 +-
 geode-membership/build.gradle                      |   17 +-
 .../src/integrationTest/resources/log4j2.xml       |    2 +-
 .../protobuf/v1/AuthorizationIntegrationTest.java  |    4 +-
 ...ueryRequestOperationHandlerIntegrationTest.java |   11 +-
 .../protobuf/security/SecureCacheImplTest.java     |    9 +-
 .../OqlQueryRequestOperationHandlerJUnitTest.java  |    3 +-
 .../geode/tools/pulse/tests/PulseTestData.java     |    4 +-
 .../tools/pulse/tests/junit/BaseServiceTest.java   |   12 +-
 .../junit/ClusterSelectedRegionServiceTest.java    |    8 +-
 .../ClusterSelectedRegionsMemberServiceTest.java   |    6 +-
 .../geode/tools/pulse/tests/ui/PulseBase.java      |   19 +-
 geode-redis/README.md                              |    4 +-
 geode-redis/build.gradle                           |   10 +-
 .../geode/redis/GeoNativeRedisAcceptanceTest.java  |   85 -
 .../redis/RenameNativeRedisAcceptanceTest.java     |   74 -
 .../redis/SortedSetNativeRedisAcceptanceTest.java  |   47 -
 .../redis/StringsNativeRedisAcceptanceTest.java    |    5 -
 .../geode/redis/ConcurrentLoopingThreads.java      |   29 +-
 .../apache/geode/redis/GeodeRedisServerRule.java   |   75 +
 .../test/dunit/rules/RedisClusterStartupRule.java  |   74 +
 .../geode/redis/CheckPrimaryBucketFunction.java    |  121 +
 .../redis/EnsurePrimaryStaysPutDUnitTest.java      |  169 ++
 .../redis/GeodeRedisServerStartupDUnitTest.java    |  107 +
 .../org/apache/geode/redis/PubSubDUnitTest.java    |  104 +-
 .../org/apache/geode/redis/RedisDistDUnitTest.java |   93 +-
 .../geode/redis/RedisSessionDistDUnitTest.java     |  256 --
 .../redis/RedisUsePersistentRegionDUnitTest.java   |   56 -
 .../geode/redis/executors/ExpireDUnitTest.java     |  117 +-
 .../geode/redis/executors/hash/HMsetDUnitTest.java |   75 +-
 .../geode/redis/executors/hash/HsetDUnitTest.java  |   75 +-
 .../redis/executors/keys/ExistsDUnitTest.java      |   23 +-
 .../redis/executors/keys/PersistDUnitTest.java     |   30 +-
 .../geode/redis/executors/set/SaddDUnitTest.java   |   75 +-
 .../geode/redis/executors/set/SremDUnitTest.java   |   75 +-
 .../redis/executors/string/StringsDUnitTest.java   |  253 ++
 .../redis/session/RedisSessionDistDUnitTest.java   |  118 +
 .../geode/redis/session/SessionDUnitTest.java      |  174 ++
 .../redis/session/SessionExpirationDUnitTest.java  |  100 +
 .../RedisSpringTestApplication.java                |    2 +-
 .../SessionController.java                         |   15 +-
 .../config/DUnitSocketAddressResolver.java         |    2 +-
 .../config/SessionListener.java                    |   20 +-
 .../config/WebMvcConfig.java                       |    2 +-
 .../apache/geode/redis/AuthIntegrationTest.java    |    1 +
 .../redis/CommandPipeliningIntegrationTest.java    |  101 +
 .../redis/ConcurrentStartIntegrationTest.java      |    5 +-
 .../org/apache/geode/redis/GeoIntegrationTest.java |  422 ----
 .../apache/geode/redis/HashesIntegrationTest.java  |  288 +--
 .../apache/geode/redis/ListsIntegrationTest.java   |  250 --
 .../apache/geode/redis/PubSubIntegrationTest.java  |   30 +-
 .../redis/RedisLockServiceIntegrationTest.java     |   81 -
 .../geode/redis/RedisServerIntegrationTest.java    |   97 -
 .../apache/geode/redis/RenameIntegrationTest.java  |   47 +-
 .../java/org/apache/geode/redis/SSLTest.java       |    1 +
 .../geode/redis/SortedSetsIntegrationTest.java     |  431 ----
 .../apache/geode/redis/StringsIntegrationTest.java |  130 +-
 .../geode/redis/general/ExistsIntegrationTest.java |  123 +-
 .../redis/general/ExpireAtIntegrationTest.java     |   27 +-
 .../geode/redis/general/ExpireIntegrationTest.java |  141 +-
 .../redis/general/FlushAllIntegrationTest.java}    |   42 +-
 .../redis/general/PersistIntegrationTest.java      |   82 +-
 .../redis/general/PexpireIntegrationTest.java      |   28 +-
 .../redis/general/ShutdownIntegrationTest.java     |   76 +
 .../internal/SubscriptionsIntegrationTest.java     |    6 -
 .../geode/redis/sets/SDiffIntegrationTest.java     |   30 +-
 .../geode/redis/sets/SInterIntegrationTest.java    |   30 +-
 .../geode/redis/sets/SMoveIntegrationTest.java     |   30 +-
 .../geode/redis/sets/SPopIntegrationTest.java      |   30 +-
 .../geode/redis/sets/SRemIntegrationTest.java      |   93 +-
 .../geode/redis/sets/SUnionIntegrationTest.java    |   30 +-
 .../geode/redis/sets/SetsIntegrationTest.java      |   34 +-
 .../apache/geode/codeAnalysis/excludedClasses.txt  |    9 -
 .../codeAnalysis/sanctionedDataSerializables.txt   |   18 +-
 .../java/org/apache/geode/internal/hll/Bits.java   |   46 -
 .../internal/hll/CardinalityMergeException.java    |   23 -
 .../org/apache/geode/internal/hll/HyperLogLog.java |  337 ---
 .../apache/geode/internal/hll/HyperLogLogPlus.java | 1865 --------------
 .../org/apache/geode/internal/hll/IBuilder.java    |   22 -
 .../apache/geode/internal/hll/ICardinality.java    |   73 -
 .../org/apache/geode/internal/hll/MurmurHash.java  |  214 --
 .../org/apache/geode/internal/hll/RegisterSet.java |  108 -
 .../org/apache/geode/redis/GeodeRedisServer.java   |  862 -------
 .../geode/redis/internal/AbstractRedisData.java    |  180 ++
 ...erNotFoundException.java => AddsDeltaInfo.java} |   33 +-
 ...NotFoundException.java => AppendDeltaInfo.java} |   26 +-
 .../geode/redis/internal/ByteArrayWrapper.java     |   77 +-
 .../org/apache/geode/redis/internal/Coder.java     |  167 +-
 .../org/apache/geode/redis/internal/Command.java   |   42 +-
 .../list/LPopExecutor.java => DeltaInfo.java}      |   13 +-
 .../list/RPopExecutor.java => DeltaType.java}      |   16 +-
 .../apache/geode/redis/internal/DoubleWrapper.java |   77 -
 .../redis/internal/ExecutionHandlerContext.java    |  280 +--
 .../org/apache/geode/redis/internal/Executor.java  |   15 +-
 .../org/apache/geode/redis/internal/GeoCoder.java  |  217 --
 .../redis/internal/GeoRadiusResponseElement.java   |   68 -
 .../geode/redis/internal/GeodeRedisServer.java     |  615 +++++
 .../geode/redis/internal/GeodeRedisService.java    |   26 +-
 .../{org/apache/hadoop/fs => }/GlobPattern.java    |   11 +-
 .../org/apache/geode/redis/internal/HashArea.java  |   30 -
 .../apache/geode/redis/internal/HashNeighbors.java |   41 -
 .../geode/redis/internal/KeyHashIdentifier.java    |   70 -
 .../apache/geode/redis/internal/KeyRegistrar.java  |  108 -
 .../geode/redis/internal/PatternSubscription.java  |    2 -
 .../org/apache/geode/redis/internal/PubSub.java    |    2 -
 .../apache/geode/redis/internal/PubSubImpl.java    |    1 -
 .../geode/redis/internal/RedisCommandType.java     |  317 +--
 .../geode/redis/internal/RedisConstants.java       |  109 +-
 .../apache/geode/redis/internal/RedisData.java}    |   41 +-
 .../apache/geode/redis/internal/RedisDataType.java |  112 +-
 .../geode/redis/internal/RedisLockService.java     |  110 -
 .../redis/internal/RedisLockServiceMBean.java      |   33 -
 .../apache/geode/redis/internal/RedisResponse.java |   93 +
 .../redis/internal/RegionCreationException.java    |   35 -
 .../geode/redis/internal/RegionProvider.java       |  580 +----
 ...erNotFoundException.java => RemsDeltaInfo.java} |   33 +-
 ...oCloseableLock.java => TimestampDeltaInfo.java} |   25 +-
 .../redis/internal/executor/AbstractExecutor.java  |  106 +-
 .../internal/executor/AbstractScanExecutor.java    |    4 +-
 .../redis/internal/executor/AuthExecutor.java      |   18 +-
 .../redis/internal/executor/CommandFunction.java   |  266 +-
 .../redis/internal/executor/DBSizeExecutor.java    |    2 +-
 .../geode/redis/internal/executor/DelExecutor.java |   29 +-
 .../redis/internal/executor/EmptyRedisHash.java    |   50 +
 .../redis/internal/executor/ExistsExecutor.java    |    8 +-
 .../internal/executor/ExpirationExecutor.java      |   41 -
 .../redis/internal/executor/ExpireAtExecutor.java  |   47 +-
 .../redis/internal/executor/ExpireExecutor.java    |   30 +-
 .../redis/internal/executor/FlushAllExecutor.java  |   22 +-
 .../redis/internal/executor/KeysExecutor.java      |   13 +-
 .../geode/redis/internal/executor/ListQuery.java   |   71 -
 .../redis/internal/executor/PersistExecutor.java   |   19 +-
 .../redis/internal/executor/QuitExecutor.java      |    8 +-
 .../redis/internal/executor/RedisHashInRegion.java |  136 ++
 .../LPushExecutor.java => RedisKeyCommands.java}   |   17 +-
 .../executor/RedisKeyCommandsFunctionExecutor.java |   65 +
 .../redis/internal/executor/RedisKeyInRegion.java  |  105 +
 .../redis/internal/executor/RenameExecutor.java    |   88 +-
 .../redis/internal/executor/ScanExecutor.java      |   10 +-
 .../executor/SingleResultRedisFunction.java        |   74 +
 .../redis/internal/executor/SortedSetQuery.java    |  335 ---
 .../geode/redis/internal/executor/TTLExecutor.java |   37 +-
 .../redis/internal/executor/TypeExecutor.java      |   10 +-
 .../{UnkownExecutor.java => UnknownExecutor.java}  |    5 +-
 .../executor/hash/GeodeRedisHashSynchronized.java  |  112 -
 .../redis/internal/executor/hash/HDelExecutor.java |   18 +-
 .../internal/executor/hash/HExistsExecutor.java    |   39 +-
 .../internal/executor/hash/HGetAllExecutor.java    |   13 +-
 .../redis/internal/executor/hash/HGetExecutor.java |   33 +-
 .../internal/executor/hash/HIncrByExecutor.java    |   89 +-
 .../executor/hash/HIncrByFloatExecutor.java        |   81 +-
 .../internal/executor/hash/HKeysExecutor.java      |   40 +-
 .../redis/internal/executor/hash/HLenExecutor.java |   35 +-
 .../internal/executor/hash/HMGetExecutor.java      |   40 +-
 .../internal/executor/hash/HMSetExecutor.java      |   15 +-
 .../internal/executor/hash/HScanExecutor.java      |   87 +-
 .../redis/internal/executor/hash/HSetExecutor.java |   14 +-
 .../internal/executor/hash/HValsExecutor.java      |   27 +-
 .../redis/internal/executor/hash/HashExecutor.java |   60 +-
 .../redis/internal/executor/hash/RedisHash.java    |  273 ++-
 .../RedisHashCommands.java}                        |   31 +-
 .../hash/RedisHashCommandsFunctionExecutor.java    |  109 +
 .../redis/internal/executor/hll/PFAddExecutor.java |   68 -
 .../internal/executor/hll/PFCountExecutor.java     |   70 -
 .../internal/executor/hll/PFMergeExecutor.java     |   75 -
 .../geode/redis/internal/executor/hll/Varint.java  |  238 --
 .../internal/executor/list/LIndexExecutor.java     |  114 -
 .../internal/executor/list/LInsertExecutor.java    |   28 -
 .../redis/internal/executor/list/LLenExecutor.java |   45 -
 .../internal/executor/list/LPushXExecutor.java     |   24 -
 .../internal/executor/list/LRangeExecutor.java     |  106 -
 .../redis/internal/executor/list/LRemExecutor.java |  109 -
 .../redis/internal/executor/list/LSetExecutor.java |  104 -
 .../internal/executor/list/LTrimExecutor.java      |  118 -
 .../redis/internal/executor/list/ListExecutor.java |  138 --
 .../redis/internal/executor/list/PopExecutor.java  |  123 -
 .../redis/internal/executor/list/PushExecutor.java |   47 -
 .../internal/executor/list/PushXExecutor.java      |   51 -
 .../internal/executor/list/RPushExecutor.java      |   25 -
 .../internal/executor/list/RPushXExecutor.java     |   23 -
 .../executor/pubsub/PsubscribeExecutor.java        |    2 +-
 .../internal/executor/pubsub/PublishExecutor.java  |   37 +-
 .../executor/pubsub/PunsubscribeExecutor.java      |    2 +-
 .../redis/internal/executor/set/EmptyRedisSet.java |   76 +
 .../redis/internal/executor/set/RedisSet.java      |  224 +-
 .../internal/executor/set/RedisSetCommands.java    |   12 +-
 .../set/RedisSetCommandsFunctionExecutor.java      |   85 +-
 .../internal/executor/set/RedisSetInRegion.java    |  256 ++
 .../redis/internal/executor/set/SAddExecutor.java  |   14 +-
 .../redis/internal/executor/set/SCardExecutor.java |   13 +-
 .../redis/internal/executor/set/SDiffExecutor.java |   19 +-
 .../internal/executor/set/SInterExecutor.java      |   19 +-
 .../internal/executor/set/SIsMemberExecutor.java   |   32 +-
 .../internal/executor/set/SMembersExecutor.java    |   20 +-
 .../redis/internal/executor/set/SMoveExecutor.java |   80 +-
 .../redis/internal/executor/set/SPopExecutor.java  |   28 +-
 .../internal/executor/set/SRandMemberExecutor.java |   38 +-
 .../redis/internal/executor/set/SRemExecutor.java  |   32 +-
 .../redis/internal/executor/set/SScanExecutor.java |   32 +-
 .../internal/executor/set/SUnionExecutor.java      |   12 +-
 .../redis/internal/executor/set/SetExecutor.java   |   29 +-
 .../redis/internal/executor/set/SetOpExecutor.java |  114 +-
 .../executor/set/SingleResultCollector.java        |   56 +
 .../internal/executor/set/StripedExecutor.java     |   11 +-
 .../executor/set/SynchronizedStripedExecutor.java  |   12 +-
 .../executor/sortedset/GeoAddExecutor.java         |   77 -
 .../executor/sortedset/GeoDistExecutor.java        |   58 -
 .../executor/sortedset/GeoHashExecutor.java        |   57 -
 .../executor/sortedset/GeoPosExecutor.java         |   60 -
 .../sortedset/GeoRadiusByMemberExecutor.java       |  126 -
 .../executor/sortedset/GeoRadiusExecutor.java      |  121 -
 .../executor/sortedset/GeoRadiusParameters.java    |  137 --
 .../executor/sortedset/GeoSortedSetExecutor.java   |   95 -
 .../executor/sortedset/SortedSetExecutor.java      |   47 -
 .../internal/executor/sortedset/ZAddExecutor.java  |   91 -
 .../internal/executor/sortedset/ZCardExecutor.java |   54 -
 .../executor/sortedset/ZCountExecutor.java         |  146 --
 .../executor/sortedset/ZIncrByExecutor.java        |   76 -
 .../executor/sortedset/ZLexCountExecutor.java      |  149 --
 .../executor/sortedset/ZRangeByLexExecutor.java    |  229 --
 .../executor/sortedset/ZRangeByScoreExecutor.java  |  220 --
 .../executor/sortedset/ZRangeExecutor.java         |  125 -
 .../internal/executor/sortedset/ZRankExecutor.java |   98 -
 .../internal/executor/sortedset/ZRemExecutor.java  |   64 -
 .../executor/sortedset/ZRemRangeByLexExecutor.java |  165 --
 .../sortedset/ZRemRangeByRankExecutor.java         |  125 -
 .../sortedset/ZRemRangeByScoreExecutor.java        |  150 --
 .../sortedset/ZRevRangeByScoreExecutor.java        |   31 -
 .../executor/sortedset/ZRevRangeExecutor.java      |   32 -
 .../executor/sortedset/ZRevRankExecutor.java       |   30 -
 .../internal/executor/sortedset/ZScanExecutor.java |  165 --
 .../executor/sortedset/ZScoreExecutor.java         |   57 -
 .../internal/executor/string/AppendExecutor.java   |   38 +-
 .../internal/executor/string/BitCountExecutor.java |    7 +-
 .../internal/executor/string/BitOpExecutor.java    |   36 +-
 .../internal/executor/string/BitPosExecutor.java   |    7 +-
 .../internal/executor/string/DecrByExecutor.java   |   59 +-
 .../internal/executor/string/DecrExecutor.java     |   69 +-
 .../internal/executor/string/GetBitExecutor.java   |    7 +-
 .../internal/executor/string/GetExecutor.java      |   21 +-
 .../internal/executor/string/GetRangeExecutor.java |    7 +-
 .../internal/executor/string/GetSetExecutor.java   |   38 +-
 .../internal/executor/string/IncrByExecutor.java   |   56 +-
 .../executor/string/IncrByFloatExecutor.java       |   13 +-
 .../internal/executor/string/IncrExecutor.java     |   64 +-
 .../internal/executor/string/MGetExecutor.java     |   25 +-
 .../internal/executor/string/MSetExecutor.java     |   36 +-
 .../internal/executor/string/MSetNXExecutor.java   |   57 +-
 .../internal/executor/string/RedisString.java      |  156 ++
 .../RedisStringCommands.java}                      |   25 +-
 .../RedisStringCommandsFunctionExecutor.java       |   77 +
 .../executor/string/RedisStringInRegion.java       |  192 ++
 .../internal/executor/string/SetBitExecutor.java   |   17 +-
 .../internal/executor/string/SetEXExecutor.java    |   17 +-
 .../internal/executor/string/SetExecutor.java      |  220 +-
 .../internal/executor/string/SetNXExecutor.java    |   22 +-
 .../redis/internal/executor/string/SetOptions.java |   69 +
 .../internal/executor/string/SetRangeExecutor.java |   29 +-
 .../internal/executor/string/StringExecutor.java   |   17 +-
 .../internal/executor/string/StrlenExecutor.java   |   11 +-
 .../executor/transactions/DiscardExecutor.java     |   40 -
 .../executor/transactions/ExecExecutor.java        |   88 -
 .../executor/transactions/MultiExecutor.java       |   45 -
 .../executor/transactions/TransactionExecutor.java |   21 -
 .../executor/transactions/UnwatchExecutor.java     |   30 -
 .../executor/transactions/WatchExecutor.java       |   30 -
 .../sanctioned-geode-redis-serializables.txt       |   78 +-
 .../internal/ExecutionHandlerContextJUnitTest.java |    6 +-
 .../redis/internal/KeyHashIdentifierTest.java      |   44 -
 .../geode/redis/internal/PubSubImplJUnitTest.java  |    3 +-
 .../redis/internal/RedisLockServiceJUnitTest.java  |  211 --
 .../redis/internal/RegionProviderJUnitTest.java    |  108 -
 .../redis/internal/SubscriptionsJUnitTest.java     |    2 -
 .../redis/internal/SupportedCommandsJUnitTest.java |  153 ++
 .../executor/AbstractExecutorJUnitTest.java        |   61 -
 ...UnitTest.java => UnknownExecutorJUnitTest.java} |    4 +-
 .../executor/general/ExistsExecutorJUnitTest.java  |   13 +-
 .../executor/string/DelExecutorJUnitTest.java      |   14 +-
 .../executor/string/GetSetExecutorJUnitTest.java   |   13 +-
 .../string/StringGetExecutorJUnitTest.java         |   53 +-
 .../string/StringSetExecutorJUnitTest.java         |  174 +-
 .../serialization/DataSerializableFixedID.java     |    2 +-
 .../geode/internal/cache/wan/WANTestBase.java      |  231 +-
 ...ParallelGatewaySenderOperation_1_DUnitTest.java |    8 +
 ...ParallelGatewaySenderOperation_2_DUnitTest.java |    4 +-
 .../cache/wan/disttx/DistTXWANDUnitTest.java       |    2 +
 .../NewWANConcurrencyCheckForDestroyDUnitTest.java |   15 +-
 .../wan/misc/NewWanAuthenticationDUnitTest.java    |    5 +-
 .../cache/wan/misc/PDXNewWanDUnitTest.java         |    9 +-
 ...atedRegion_ParallelWANPropagationDUnitTest.java |    7 +-
 .../internal/cache/wan/misc/WANSSLDUnitTest.java   |    3 +-
 ...ANPersistenceEnabledGatewaySenderDUnitTest.java |  291 +++
 .../wan/parallel/ParallelWANStatsDUnitTest.java    |  663 +++--
 ...lGatewaySenderDistributedDeadlockDUnitTest.java |    5 +-
 ...rialGatewaySenderOperationsDistributedTest.java |   17 +-
 ...ANPersistenceEnabledGatewaySenderDUnitTest.java |  148 ++
 .../cache/wan/serial/SerialWANStatsDUnitTest.java  |  383 ++-
 .../WANHostNameVerificationDistributedTest.java    |    9 +-
 ...CreateDestroyGatewaySenderCommandDUnitTest.java |   13 +-
 .../StartGatewaySenderCommandDUnitTest.java        |   97 +
 .../cache/wan/wancommand/WANCommandUtils.java      |    6 +-
 .../cli/commands/AlterRegionCommandDUnitTest.java  |   22 +-
 .../AlterRegionCommandWithRemoteLocator.java       |   67 +-
 .../cli/commands/CreateRegionCommandDUnitTest.java |    9 +-
 .../cache/wan/misc/WANConfigurationJUnitTest.java  |   25 +-
 .../wan/GatewaySenderEventRemoteDispatcher.java    |    4 +-
 .../cache/wan/GatewaySenderFactoryImpl.java        |   13 +
 .../wan/parallel/ParallelGatewaySenderImpl.java    |   12 +-
 ...currentParallelGatewaySenderEventProcessor.java |    9 +-
 .../RemoteParallelGatewaySenderEventProcessor.java |    9 +-
 ...oncurrentSerialGatewaySenderEventProcessor.java |    8 +-
 .../RemoteSerialGatewaySenderEventProcessor.java   |    4 +-
 .../cache/wan/serial/SerialGatewaySenderImpl.java  |   34 +-
 .../parallel/ParallelGatewaySenderImplTest.java    |   92 +
 .../wan/serial/SerialGatewaySenderImplTest.java    |   89 +-
 .../web/controllers/AddFreeItemToOrders.java       |    5 +-
 .../web/controllers/RestAccessControllerTest.java  |   49 +-
 .../CustomMappingJackson2HttpMessageConverter.java |    6 +
 .../management/client/GetStartingMemberTest.java   |   93 +
 .../MemberManagementServiceRestDUnitTest.java}     |    6 +-
 .../rest/RegionManagementIntegrationTest.java      |    3 +-
 .../CustomMappingJackson2HttpMessageConverter.java |    6 +
 .../commands/ShutdownCommandOverHttpDUnitTest.java |   44 +-
 gradle/standard-subproject-configuration.gradle    |    2 +-
 957 files changed, 23469 insertions(+), 25210 deletions(-)
 copy {geode-core/src/main/java/org/apache/geode/internal/cache/util => geode-common/src/main/java/org/apache/geode/util/internal}/UncheckedUtils.java (68%)
 create mode 100644 geode-common/src/test/java/org/apache/geode/util/internal/UncheckedUtilsTest.java
 create mode 100644 geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ParallelDiskStoreRecoveryDUnitTest.java
 create mode 100644 geode-core/src/integrationTest/java/org/apache/geode/distributed/LoadClusterConfigFromDirIntegrationTest.java
 rename geode-core/src/main/java/org/apache/geode/cache/client/proxy/{SniSocketFactory.java => SniProxySocketFactory.java} (90%)
 create mode 100644 geode-core/src/main/java/org/apache/geode/internal/cache/TXLastEventInTransactionUtils.java
 rename geode-core/src/main/java/org/apache/geode/internal/cache/{util/UncheckedUtils.java => execute/util/TypedFunctionService.java} (61%)
 rename geode-core/src/main/java/org/apache/geode/{management/internal => internal/net}/SSLUtil.java (73%)
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/GeoCoord.java => geode-core/src/main/java/org/apache/geode/management/internal/operation/OperationPerformer.java (68%)
 create mode 100644 geode-core/src/test/java/org/apache/geode/cache/asyncqueue/internal/ParallelAsyncEventQueueImplTest.java
 create mode 100644 geode-core/src/test/java/org/apache/geode/internal/cache/TXLastEventInTransactionUtilsTest.java
 create mode 100644 geode-core/src/test/java/org/apache/geode/internal/cache/wan/serial/SerialGatewaySenderQueueJUnitTest.java
 create mode 100644 geode-core/src/test/java/org/apache/geode/internal/net/SSLUtilTest.java
 create mode 100644 geode-core/src/test/java/org/apache/geode/management/internal/beans/GatewaySenderMBeanBridgeTest.java
 copy geode-experimental-driver/src/integrationTest/java/org/apache/geode/experimental/driver/QueryServiceIntegrationTest.java => geode-core/src/test/java/org/apache/geode/management/internal/beans/GatewaySenderMBeanTest.java (54%)
 create mode 100644 geode-core/src/test/java/org/apache/geode/management/internal/functions/CacheRealizationFunctionTest.java
 create mode 100644 geode-docs/images/redis_api_for_geode.png
 delete mode 100644 geode-docs/tools_modules/redis_adapter.html.md.erb
 create mode 100644 geode-docs/tools_modules/redis_api_for_geode.html.md.erb
 create mode 100644 geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandTest.java
 create mode 100644 geode-junit/src/main/java/org/apache/geode/test/junit/rules/accessible/AccessibleErrorCollector.java
 delete mode 100755 geode-redis/src/acceptanceTest/java/org/apache/geode/redis/GeoNativeRedisAcceptanceTest.java
 delete mode 100644 geode-redis/src/acceptanceTest/java/org/apache/geode/redis/RenameNativeRedisAcceptanceTest.java
 delete mode 100755 geode-redis/src/acceptanceTest/java/org/apache/geode/redis/SortedSetNativeRedisAcceptanceTest.java
 create mode 100644 geode-redis/src/commonTest/java/org/apache/geode/redis/GeodeRedisServerRule.java
 create mode 100644 geode-redis/src/commonTest/java/org/apache/geode/test/dunit/rules/RedisClusterStartupRule.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/CheckPrimaryBucketFunction.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/EnsurePrimaryStaysPutDUnitTest.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/GeodeRedisServerStartupDUnitTest.java
 delete mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/RedisSessionDistDUnitTest.java
 delete mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/RedisUsePersistentRegionDUnitTest.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/executors/string/StringsDUnitTest.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/session/RedisSessionDistDUnitTest.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/session/SessionDUnitTest.java
 create mode 100644 geode-redis/src/distributedTest/java/org/apache/geode/redis/session/SessionExpirationDUnitTest.java
 rename geode-redis/src/distributedTest/java/org/apache/geode/redis/{ => session}/springRedisTestApplication/RedisSpringTestApplication.java (94%)
 rename geode-redis/src/distributedTest/java/org/apache/geode/redis/{ => session}/springRedisTestApplication/SessionController.java (85%)
 rename geode-redis/src/distributedTest/java/org/apache/geode/redis/{ => session}/springRedisTestApplication/config/DUnitSocketAddressResolver.java (95%)
 rename geode-redis/src/distributedTest/java/org/apache/geode/redis/{ => session}/springRedisTestApplication/config/SessionListener.java (62%)
 rename geode-redis/src/distributedTest/java/org/apache/geode/redis/{ => session}/springRedisTestApplication/config/WebMvcConfig.java (95%)
 create mode 100644 geode-redis/src/integrationTest/java/org/apache/geode/redis/CommandPipeliningIntegrationTest.java
 delete mode 100755 geode-redis/src/integrationTest/java/org/apache/geode/redis/GeoIntegrationTest.java
 delete mode 100755 geode-redis/src/integrationTest/java/org/apache/geode/redis/ListsIntegrationTest.java
 delete mode 100644 geode-redis/src/integrationTest/java/org/apache/geode/redis/RedisLockServiceIntegrationTest.java
 delete mode 100644 geode-redis/src/integrationTest/java/org/apache/geode/redis/RedisServerIntegrationTest.java
 delete mode 100755 geode-redis/src/integrationTest/java/org/apache/geode/redis/SortedSetsIntegrationTest.java
 rename geode-redis/src/{acceptanceTest/java/org/apache/geode/redis/ListsNativeRedisAcceptanceTest.java => integrationTest/java/org/apache/geode/redis/general/FlushAllIntegrationTest.java} (53%)
 mode change 100755 => 100644
 create mode 100644 geode-redis/src/integrationTest/java/org/apache/geode/redis/general/ShutdownIntegrationTest.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/Bits.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/CardinalityMergeException.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/HyperLogLog.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/HyperLogLogPlus.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/IBuilder.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/ICardinality.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/MurmurHash.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/internal/hll/RegisterSet.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/GeodeRedisServer.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/AbstractRedisData.java
 copy geode-redis/src/main/java/org/apache/geode/redis/internal/{MemberNotFoundException.java => AddsDeltaInfo.java} (55%)
 copy geode-redis/src/main/java/org/apache/geode/redis/internal/{MemberNotFoundException.java => AppendDeltaInfo.java} (64%)
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/{executor/list/LPopExecutor.java => DeltaInfo.java} (80%)
 mode change 100755 => 100644
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/{executor/list/RPopExecutor.java => DeltaType.java} (80%)
 mode change 100755 => 100644
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/DoubleWrapper.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/GeoCoder.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/GeoRadiusResponseElement.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/GeodeRedisServer.java
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/{org/apache/hadoop/fs => }/GlobPattern.java (97%)
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/HashArea.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/HashNeighbors.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/KeyHashIdentifier.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/KeyRegistrar.java
 rename geode-redis/src/{test/java/org/apache/geode/redis/internal/GeoCoderJUnitTest.java => main/java/org/apache/geode/redis/internal/RedisData.java} (59%)
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/RedisLockService.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/RedisLockServiceMBean.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/RedisResponse.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/RegionCreationException.java
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/{MemberNotFoundException.java => RemsDeltaInfo.java} (55%)
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/{AutoCloseableLock.java => TimestampDeltaInfo.java} (67%)
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/EmptyRedisHash.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ExpirationExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/ListQuery.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/RedisHashInRegion.java
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/executor/{list/LPushExecutor.java => RedisKeyCommands.java} (67%)
 mode change 100755 => 100644
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/RedisKeyCommandsFunctionExecutor.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/RedisKeyInRegion.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SingleResultRedisFunction.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/SortedSetQuery.java
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/executor/{UnkownExecutor.java => UnknownExecutor.java} (92%)
 mode change 100755 => 100644
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/GeodeRedisHashSynchronized.java
 copy geode-redis/src/main/java/org/apache/geode/redis/internal/executor/{set/RedisSetCommands.java => hash/RedisHashCommands.java} (51%)
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hash/RedisHashCommandsFunctionExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hll/PFAddExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hll/PFCountExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hll/PFMergeExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/hll/Varint.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LIndexExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LInsertExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LLenExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LPushXExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LRangeExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LRemExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LSetExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/LTrimExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/ListExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/PopExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/PushExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/PushXExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/RPushExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/list/RPushXExecutor.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/set/EmptyRedisSet.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/set/RedisSetInRegion.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/set/SingleResultCollector.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoAddExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoDistExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoHashExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoPosExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoRadiusByMemberExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoRadiusExecutor.java
 delete mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoRadiusParameters.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/GeoSortedSetExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/SortedSetExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZAddExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZCardExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZCountExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZIncrByExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZLexCountExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRangeByLexExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRangeByScoreExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRangeExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRankExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRemExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRemRangeByLexExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRemRangeByRankExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRemRangeByScoreExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRevRangeByScoreExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRevRangeExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZRevRankExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZScanExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/sortedset/ZScoreExecutor.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisString.java
 rename geode-redis/src/main/java/org/apache/geode/redis/internal/executor/{hll/HllExecutor.java => string/RedisStringCommands.java} (57%)
 mode change 100755 => 100644
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionExecutor.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringInRegion.java
 create mode 100644 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/SetOptions.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/transactions/DiscardExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/transactions/ExecExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/transactions/MultiExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/transactions/TransactionExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/transactions/UnwatchExecutor.java
 delete mode 100755 geode-redis/src/main/java/org/apache/geode/redis/internal/executor/transactions/WatchExecutor.java
 delete mode 100644 geode-redis/src/test/java/org/apache/geode/redis/internal/KeyHashIdentifierTest.java
 delete mode 100644 geode-redis/src/test/java/org/apache/geode/redis/internal/RedisLockServiceJUnitTest.java
 delete mode 100644 geode-redis/src/test/java/org/apache/geode/redis/internal/RegionProviderJUnitTest.java
 create mode 100644 geode-redis/src/test/java/org/apache/geode/redis/internal/SupportedCommandsJUnitTest.java
 delete mode 100644 geode-redis/src/test/java/org/apache/geode/redis/internal/executor/AbstractExecutorJUnitTest.java
 rename geode-redis/src/test/java/org/apache/geode/redis/internal/executor/{UnkownExecutorJUnitTest.java => UnknownExecutorJUnitTest.java} (94%)
 create mode 100644 geode-wan/src/test/java/org/apache/geode/internal/cache/wan/parallel/ParallelGatewaySenderImplTest.java
 copy geode-core/src/test/java/org/apache/geode/cache/asyncqueue/internal/SerialAsyncEventQueueImplTest.java => geode-wan/src/test/java/org/apache/geode/internal/cache/wan/serial/SerialGatewaySenderImplTest.java (54%)
 create mode 100644 geode-web-management/src/distributedTest/java/org/apache/geode/management/client/GetStartingMemberTest.java
 rename geode-web-management/src/{integrationTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceRestIntegrationTest.java => distributedTest/java/org/apache/geode/management/client/MemberManagementServiceRestDUnitTest.java} (96%)


[geode] 07/11: GEODE-7667: Add a 'clear' gfsh command for PR and RR clear (#4818)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit b7b3223938652b615f524bf6c8612db2f0cd5ffa
Author: BenjaminPerryRoss <39...@users.noreply.github.com>
AuthorDate: Tue May 5 11:40:34 2020 -0700

    GEODE-7667: Add a 'clear' gfsh command for PR and RR clear (#4818)
    
    * Added clear command and modified remove functionality to clear PR
    
    Authored-by: Benjamin Ross <br...@pivotal.io>
---
 .../geode/management/internal/i18n/CliStrings.java |  14 ++-
 .../cli/commands/ClearCommandDUnitTest.java        | 120 +++++++++++++++++++++
 .../cli/commands/RemoveCommandDUnitTest.java       |  13 ++-
 .../{RemoveCommand.java => ClearCommand.java}      |  53 ++++-----
 .../cli/commands/CommandAvailabilityIndicator.java |   1 +
 .../internal/cli/commands/RemoveCommand.java       |   9 +-
 .../internal/cli/domain/DataCommandResult.java     |  12 +++
 .../cli/functions/DataCommandFunction.java         |  23 ++--
 .../internal/cli/commands/ClearCommandTest.java    | 115 ++++++++++++++++++++
 9 files changed, 309 insertions(+), 51 deletions(-)

diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java b/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
index 75db5b2..b43add8 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
@@ -811,6 +811,14 @@ public class CliStrings {
   public static final String CLEAR_DEFINED_INDEX__SUCCESS__MSG =
       "Index definitions successfully cleared";
 
+  /* clear region */
+  public static final String CLEAR_REGION = "clear region";
+  public static final String CLEAR_REGION_HELP =
+      "Clears/Removes all keys from the specified region.";
+  public static final String CLEAR_REGION_REGION_NAME = "name";
+  public static final String CLEAR_REGION_REGION_NAME_HELP = "Region to clear keys from.";
+  public static final String CLEAR_REGION_CLEARED_ALL_KEYS = "Cleared all keys in the region";
+
   /* create region */
   public static final String CREATE_REGION = "create region";
   public static final String CREATE_REGION__HELP =
@@ -1930,9 +1938,9 @@ public class CliStrings {
   public static final String REMOVE__MSG__KEY_EMPTY = "Key is Null";
   public static final String REMOVE__MSG__REGION_NOT_FOUND = "Region <{0}> Not Found";
   public static final String REMOVE__MSG__KEY_NOT_FOUND_REGION = "Key is not present in the region";
-  public static final String REMOVE__MSG__CLEARED_ALL_CLEARS = "Cleared all keys in the region";
-  public static final String REMOVE__MSG__CLEARALL_NOT_SUPPORTED_FOR_PARTITIONREGION =
-      "Option --" + REMOVE__ALL + " is not supported on partitioned region";
+  public static final String REMOVE__MSG__CLEARALL_DEPRECATION_WARNING =
+      "Warning: The --all option for the 'remove' command is deprecated. Please"
+          + " use the 'clear' command instead.";
 
   /* resume gateway-sender */
   public static final String RESUME_GATEWAYSENDER = "resume gateway-sender";
diff --git a/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/ClearCommandDUnitTest.java b/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/ClearCommandDUnitTest.java
new file mode 100644
index 0000000..e51fc0f
--- /dev/null
+++ b/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/ClearCommandDUnitTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.management.internal.cli.commands;
+
+import static org.apache.geode.management.internal.cli.commands.RemoveCommand.REGION_NOT_FOUND;
+import static org.apache.geode.management.internal.i18n.CliStrings.CLEAR_REGION_CLEARED_ALL_KEYS;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
+import org.apache.geode.management.internal.i18n.CliStrings;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+import org.apache.geode.test.junit.rules.VMProvider;
+
+@RunWith(JUnitParamsRunner.class)
+public class ClearCommandDUnitTest {
+  private static final String REPLICATE_REGION_NAME = "replicateRegion";
+  private static final String PARTITIONED_REGION_NAME = "partitionedRegion";
+  private static final String EMPTY_STRING = "";
+  private static final int NUM_ENTRIES = 200;
+
+  @Rule
+  public ClusterStartupRule clusterStartupRule = new ClusterStartupRule();
+
+  @Rule
+  public GfshCommandRule gfsh = new GfshCommandRule();
+
+  private MemberVM locator;
+  private MemberVM server1;
+  private MemberVM server2;
+
+  @Before
+  public void setup() throws Exception {
+    locator = clusterStartupRule.startLocatorVM(0);
+    server1 = clusterStartupRule.startServerVM(1, locator.getPort());
+    server2 = clusterStartupRule.startServerVM(2, locator.getPort());
+
+    gfsh.connectAndVerify(locator);
+    gfsh.executeAndAssertThat("create region --name=" + REPLICATE_REGION_NAME + " --type=REPLICATE")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + PARTITIONED_REGION_NAME + " --type=PARTITION").statusIsSuccess();
+
+    locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/" + REPLICATE_REGION_NAME, 2);
+    locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/" + PARTITIONED_REGION_NAME, 2);
+
+    VMProvider.invokeInEveryMember(ClearCommandDUnitTest::populateTestRegions, server1, server2);
+  }
+
+  private static void populateTestRegions() {
+    Cache cache = CacheFactory.getAnyInstance();
+
+    Region<String, String> replicateRegion = cache.getRegion(REPLICATE_REGION_NAME);
+    replicateRegion.put(EMPTY_STRING, "valueForEmptyKey");
+    for (int i = 0; i < NUM_ENTRIES; i++) {
+      replicateRegion.put("key" + i, "value" + i);
+    }
+
+    Region<String, String> partitionedRegion = cache.getRegion(PARTITIONED_REGION_NAME);
+    replicateRegion.put(EMPTY_STRING, "valueForEmptyKey");
+    for (int i = 0; i < NUM_ENTRIES; i++) {
+      partitionedRegion.put("key" + i, "value" + i);
+    }
+  }
+
+  @Test
+  public void clearFailsWhenRegionIsNotFound() {
+    String invalidRegionName = "NotAValidRegion";
+    String command = new CommandStringBuilder(CliStrings.CLEAR_REGION)
+        .addOption(CliStrings.CLEAR_REGION_REGION_NAME, invalidRegionName).getCommandString();
+    gfsh.executeAndAssertThat(command).statusIsError()
+        .containsOutput(String.format(REGION_NOT_FOUND, "/" + invalidRegionName));
+  }
+
+  @Test
+  @Parameters({REPLICATE_REGION_NAME, PARTITIONED_REGION_NAME})
+  public void clearSucceedsWithValidRegion(String regionName) {
+    String command = new CommandStringBuilder(CliStrings.CLEAR_REGION)
+        .addOption(CliStrings.CLEAR_REGION_REGION_NAME, regionName).getCommandString();
+
+    gfsh.executeAndAssertThat(command).statusIsSuccess();
+
+    assertThat(gfsh.getGfshOutput()).contains(CLEAR_REGION_CLEARED_ALL_KEYS);
+
+    server1.invoke(() -> verifyAllKeysAreRemoved(regionName));
+    server2.invoke(() -> verifyAllKeysAreRemoved(regionName));
+  }
+
+  private static void verifyAllKeysAreRemoved(String regionName) {
+    Region region = getRegion(regionName);
+    assertThat(region.size()).isEqualTo(0);
+  }
+
+  private static Region getRegion(String regionName) {
+    return CacheFactory.getAnyInstance().getRegion(regionName);
+  }
+}
diff --git a/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java b/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java
index 92a65ec..2a88d64 100644
--- a/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java
+++ b/geode-gfsh/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/RemoveCommandDUnitTest.java
@@ -16,6 +16,7 @@ package org.apache.geode.management.internal.cli.commands;
 
 import static org.apache.geode.cache.Region.SEPARATOR;
 import static org.apache.geode.management.internal.cli.commands.RemoveCommand.REGION_NOT_FOUND;
+import static org.apache.geode.management.internal.i18n.CliStrings.CLEAR_REGION_CLEARED_ALL_KEYS;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import org.junit.Before;
@@ -25,6 +26,7 @@ import org.junit.Test;
 import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.CacheFactory;
 import org.apache.geode.cache.Region;
+import org.apache.geode.management.internal.i18n.CliStrings;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
 import org.apache.geode.test.junit.rules.GfshCommandRule;
@@ -128,7 +130,8 @@ public class RemoveCommandDUnitTest {
     gfsh.executeAndAssertThat("list regions").statusIsSuccess();
     gfsh.executeAndAssertThat(command).statusIsSuccess();
 
-    assertThat(gfsh.getGfshOutput()).contains("Cleared all keys in the region");
+    assertThat(gfsh.getGfshOutput()).contains(CLEAR_REGION_CLEARED_ALL_KEYS)
+        .contains(CliStrings.REMOVE__MSG__CLEARALL_DEPRECATION_WARNING);
 
     server1.invoke(() -> verifyAllKeysAreRemoved(REPLICATE_REGION_NAME));
     server2.invoke(() -> verifyAllKeysAreRemoved(REPLICATE_REGION_NAME));
@@ -139,11 +142,13 @@ public class RemoveCommandDUnitTest {
   public void removeAllFromPartitionedRegion() {
     String command = "remove --all --region=" + PARTITIONED_REGION_NAME;
 
-    // Maybe this should return an "error" status, but the current behavior is status "OK"
     gfsh.executeAndAssertThat(command).statusIsSuccess();
 
-    assertThat(gfsh.getGfshOutput())
-        .contains("Option --all is not supported on partitioned region");
+    assertThat(gfsh.getGfshOutput()).contains(CLEAR_REGION_CLEARED_ALL_KEYS)
+        .contains(CliStrings.REMOVE__MSG__CLEARALL_DEPRECATION_WARNING);;
+
+    server1.invoke(() -> verifyAllKeysAreRemoved(PARTITIONED_REGION_NAME));
+    server2.invoke(() -> verifyAllKeysAreRemoved(PARTITIONED_REGION_NAME));
   }
 
   /**
diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ClearCommand.java
similarity index 63%
copy from geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java
copy to geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ClearCommand.java
index c15f01f..75ac720 100644
--- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java
+++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ClearCommand.java
@@ -38,59 +38,52 @@ import org.apache.geode.management.internal.i18n.CliStrings;
 import org.apache.geode.security.ResourcePermission.Operation;
 import org.apache.geode.security.ResourcePermission.Resource;
 
-public class RemoveCommand extends GfshCommand {
+public class ClearCommand extends GfshCommand {
   public static final String REGION_NOT_FOUND = "Region <%s> not found in any of the members";
 
   @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DATA, CliStrings.TOPIC_GEODE_REGION})
-  @CliCommand(value = {CliStrings.REMOVE}, help = CliStrings.REMOVE__HELP)
-  public ResultModel remove(
-      @CliOption(key = {CliStrings.REMOVE__KEY}, help = CliStrings.REMOVE__KEY__HELP,
-          specifiedDefaultValue = "") String key,
-      @CliOption(key = {CliStrings.REMOVE__REGION}, mandatory = true,
-          help = CliStrings.REMOVE__REGION__HELP,
-          optionContext = ConverterHint.REGION_PATH) String regionPath,
-      @CliOption(key = CliStrings.REMOVE__ALL, help = CliStrings.REMOVE__ALL__HELP,
-          specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") boolean removeAllKeys,
-      @CliOption(key = {CliStrings.REMOVE__KEYCLASS},
-          help = CliStrings.REMOVE__KEYCLASS__HELP) String keyClass) {
-    Cache cache = getCache();
+  @CliCommand(value = {CliStrings.CLEAR_REGION}, help = CliStrings.CLEAR_REGION_HELP)
+  public ResultModel clear(
+      @CliOption(key = {CliStrings.CLEAR_REGION_REGION_NAME}, mandatory = true,
+          help = CliStrings.CLEAR_REGION_REGION_NAME_HELP,
+          optionContext = ConverterHint.REGION_PATH) String regionPath) {
 
-    if (!removeAllKeys && (key == null)) {
-      return new ResultModel().createError(CliStrings.REMOVE__MSG__KEY_EMPTY);
-    }
+    Cache cache = getCache();
 
-    if (removeAllKeys) {
-      authorize(Resource.DATA, Operation.WRITE, regionPath);
-    } else {
-      authorize(Resource.DATA, Operation.WRITE, regionPath, key);
-    }
+    authorize(Resource.DATA, Operation.WRITE, regionPath);
 
-    key = DataCommandsUtils.makeBrokenJsonCompliant(key);
 
     Region region = cache.getRegion(regionPath);
-    DataCommandFunction removefn = new DataCommandFunction();
+    DataCommandFunction clearfn = createCommandFunction();
     DataCommandResult dataResult;
     if (region == null) {
       Set<DistributedMember> memberList = findAnyMembersForRegion(regionPath);
 
       if (CollectionUtils.isEmpty(memberList)) {
-        return new ResultModel().createError(String.format(REGION_NOT_FOUND, regionPath));
+        return ResultModel.createError(String.format(REGION_NOT_FOUND, regionPath));
       }
 
       DataCommandRequest request = new DataCommandRequest();
       request.setCommand(CliStrings.REMOVE);
-      request.setKey(key);
-      request.setKeyClass(keyClass);
-      request.setRemoveAllKeys(removeAllKeys ? "ALL" : null);
+      request.setRemoveAllKeys("ALL");
       request.setRegionName(regionPath);
-      dataResult = callFunctionForRegion(request, removefn, memberList);
+      dataResult = callFunctionForRegion(request, clearfn, memberList);
     } else {
-      dataResult = removefn.remove(key, keyClass, regionPath, removeAllKeys ? "ALL" : null,
+      dataResult = clearfn.remove(null, null, regionPath, "ALL",
           (InternalCache) cache);
     }
 
-    dataResult.setKeyClass(keyClass);
+    dataResult.setKeyClass(null);
 
     return dataResult.toResultModel();
   }
+
+  DataCommandResult callFunctionForRegion(DataCommandRequest request, DataCommandFunction clearfn,
+      Set<DistributedMember> memberList) {
+    return DataCommandsUtils.callFunctionForRegion(request, clearfn, memberList);
+  }
+
+  DataCommandFunction createCommandFunction() {
+    return new DataCommandFunction();
+  }
 }
diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CommandAvailabilityIndicator.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CommandAvailabilityIndicator.java
index ae0b7c4..50f811d 100644
--- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CommandAvailabilityIndicator.java
+++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CommandAvailabilityIndicator.java
@@ -26,6 +26,7 @@ public class CommandAvailabilityIndicator extends GfshCommand {
       CliStrings.DESCRIBE_CONFIG, CliStrings.EXPORT_CONFIG, CliStrings.ALTER_RUNTIME_CONFIG,
       CliStrings.ALTER_REGION, CliStrings.CREATE_REGION, CliStrings.DESTROY_REGION,
       CliStrings.REBALANCE, CliStrings.GET, CliStrings.PUT, CliStrings.REMOVE,
+      CliStrings.CLEAR_REGION,
       CliStrings.LOCATE_ENTRY, CliStrings.QUERY, CliStrings.IMPORT_DATA, CliStrings.EXPORT_DATA,
       CliStrings.DEPLOY, CliStrings.UNDEPLOY, CliStrings.LIST_DEPLOYED,
       CliStrings.BACKUP_DISK_STORE, CliStrings.COMPACT_DISK_STORE, CliStrings.DESCRIBE_DISK_STORE,
diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java
index c15f01f..062428d 100644
--- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java
+++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/RemoveCommand.java
@@ -90,7 +90,14 @@ public class RemoveCommand extends GfshCommand {
     }
 
     dataResult.setKeyClass(keyClass);
+    ResultModel result;
 
-    return dataResult.toResultModel();
+    if (removeAllKeys) {
+      result = dataResult.toResultModel(CliStrings.REMOVE__MSG__CLEARALL_DEPRECATION_WARNING);
+    } else {
+      result = dataResult.toResultModel();
+    }
+
+    return result;
   }
 }
diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java
index 3f00a95..6bc91cb 100644
--- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java
+++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/DataCommandResult.java
@@ -33,6 +33,7 @@ import org.apache.geode.cache.query.internal.Undefined;
 import org.apache.geode.management.cli.Result;
 import org.apache.geode.management.internal.cli.GfshParser;
 import org.apache.geode.management.internal.cli.result.model.DataResultModel;
+import org.apache.geode.management.internal.cli.result.model.InfoResultModel;
 import org.apache.geode.management.internal.cli.result.model.ResultModel;
 import org.apache.geode.management.internal.cli.result.model.TabularResultModel;
 import org.apache.geode.management.internal.i18n.CliStrings;
@@ -49,6 +50,7 @@ public class DataCommandResult implements Serializable {
 
   public static final Logger logger = LogManager.getLogger();
   public static final String DATA_INFO_SECTION = "data-info";
+  public static final String WARNING_INFO_SECTION = "header-info";
   public static final String QUERY_SECTION = "query";
   public static final String LOCATION_SECTION = "location";
   private String command;
@@ -372,6 +374,10 @@ public class DataCommandResult implements Serializable {
   }
 
   public ResultModel toResultModel() {
+    return toResultModel("");
+  }
+
+  public ResultModel toResultModel(String warningMessage) {
     if (StringUtils.isEmpty(keyClass)) {
       keyClass = "java.lang.String";
     }
@@ -381,6 +387,12 @@ public class DataCommandResult implements Serializable {
     }
 
     ResultModel result = new ResultModel();
+
+    if (warningMessage != null && !warningMessage.isEmpty()) {
+      InfoResultModel info = result.addInfo(WARNING_INFO_SECTION);
+      info.addLine(warningMessage);
+    }
+
     DataResultModel data = result.addData(DATA_INFO_SECTION);
 
     if (errorString != null) {
diff --git a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java
index 17cf20f..44c84b5 100644
--- a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java
+++ b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/functions/DataCommandFunction.java
@@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.Logger;
 
-import org.apache.geode.cache.DataPolicy;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.partition.PartitionRegionHelper;
@@ -315,22 +314,20 @@ public class DataCommandFunction implements InternalFunction<DataCommandRequest>
               CliStrings.REMOVE__MSG__KEY_NOT_FOUND_REGION, false);
         }
       } else {
-        DataPolicy policy = region.getAttributes().getDataPolicy();
-        if (!policy.withPartitioning()) {
-          region.clear();
-          if (logger.isDebugEnabled()) {
-            logger.debug("Cleared all keys in the region - {}", regionName);
-          }
-          return DataCommandResult.createRemoveInfoResult(key, null, null,
-              CliStrings.format(CliStrings.REMOVE__MSG__CLEARED_ALL_CLEARS, regionName), true);
-        } else {
-          return DataCommandResult.createRemoveInfoResult(key, null, null,
-              CliStrings.REMOVE__MSG__CLEARALL_NOT_SUPPORTED_FOR_PARTITIONREGION, false);
-        }
+        return clear(region, regionName);
       }
     }
   }
 
+  public DataCommandResult clear(Region region, String regionName) {
+    region.clear();
+    if (logger.isDebugEnabled()) {
+      logger.debug("Cleared all keys in the region - {}", regionName);
+    }
+    return DataCommandResult.createRemoveInfoResult(null, null, null,
+        CliStrings.format(CliStrings.CLEAR_REGION_CLEARED_ALL_KEYS, regionName), true);
+  }
+
   @SuppressWarnings({"rawtypes"})
   public DataCommandResult get(Object principal, String key, String keyClass, String valueClass,
       String regionName, Boolean loadOnCacheMiss, InternalCache cache) {
diff --git a/geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/ClearCommandTest.java b/geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/ClearCommandTest.java
new file mode 100644
index 0000000..a716ef5
--- /dev/null
+++ b/geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/ClearCommandTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.management.internal.cli.commands;
+
+
+import static org.apache.geode.management.internal.cli.commands.ClearCommand.REGION_NOT_FOUND;
+import static org.apache.geode.management.internal.i18n.CliStrings.CLEAR_REGION;
+import static org.apache.geode.management.internal.i18n.CliStrings.CLEAR_REGION_REGION_NAME;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.domain.DataCommandResult;
+import org.apache.geode.management.internal.cli.functions.DataCommandFunction;
+import org.apache.geode.management.internal.cli.result.model.ResultModel;
+import org.apache.geode.test.junit.rules.GfshParserRule;
+
+public class ClearCommandTest {
+
+  @ClassRule
+  public static GfshParserRule gfsh = new GfshParserRule();
+
+  static final String regionName = "regionName";
+  static final String success = "SUCCESS";
+
+  InternalCache cache;
+  ClearCommand command;
+  Region<Object, Object> region;
+  Set<DistributedMember> membersList;
+  DistributedMember member;
+  DataCommandResult dataResult;
+
+  @SuppressWarnings("unchecked")
+  @Before
+  public void setup() {
+    cache = mock(InternalCache.class);
+    command = spy(new ClearCommand());
+    region = mock(Region.class);
+    dataResult = mock(DataCommandResult.class);
+
+    membersList = new HashSet<>();
+    membersList.add(member);
+
+    doNothing().when(command).authorize(any(), any(), anyString());
+    doReturn(cache).when(command).getCache();
+    doReturn(membersList).when(command).findAnyMembersForRegion(anyString());
+
+    ResultModel result = ResultModel.createInfo(success);
+    doReturn(result).when(dataResult).toResultModel();
+  }
+
+  @Test
+  public void commandReturnsErrorIfRegionIsNotFound() {
+    membersList.clear();
+
+    gfsh.executeAndAssertThat(command,
+        CLEAR_REGION + " --" + CLEAR_REGION_REGION_NAME + "=/" + regionName)
+        .statusIsError().containsOutput(String.format(REGION_NOT_FOUND, "/" + regionName));
+  }
+
+  @Test
+  public void commandReturnsSuccessfullyIfRegionIsFoundOnServersButNotLocator() {
+    doReturn(dataResult).when(command).callFunctionForRegion(any(), any(), any());
+
+    gfsh.executeAndAssertThat(command,
+        CLEAR_REGION + " --" + CLEAR_REGION_REGION_NAME + "=/" + regionName)
+        .statusIsSuccess().containsOutput(success);
+
+    verify(command).callFunctionForRegion(any(), any(), any());
+  }
+
+  @Test
+  public void commandReturnsSuccessfullyIfRegionIsFoundOnLocator() {
+    DataCommandFunction dataCommandFunction = mock(DataCommandFunction.class);
+    doReturn(dataCommandFunction).when(command).createCommandFunction();
+    when(cache.getRegion("/" + regionName)).thenReturn(region);
+
+    doReturn(dataResult).when(dataCommandFunction)
+        .remove(null, null, "/" + regionName, "ALL", cache);
+
+    gfsh.executeAndAssertThat(command,
+        CLEAR_REGION + " --" + CLEAR_REGION_REGION_NAME + "=/" + regionName)
+        .statusIsSuccess().containsOutput(success);
+
+    verify(dataCommandFunction).remove(null, null, "/" + regionName,
+        "ALL", cache);
+  }
+}


[geode] 06/11: GEODE-7676: Add PR clear with expiration tests (#4970)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit f3168e9d30003a06e55b8e531374f3f766876139
Author: Juan José Ramos <ju...@users.noreply.github.com>
AuthorDate: Wed Apr 22 14:18:07 2020 +0100

    GEODE-7676: Add PR clear with expiration tests (#4970)
    
    Added distributed tests to verify the clear operation on Partitioned
    Regions works as expected when expiration is configured.
    
    - Added unit and distributed tests.
    - Fixed LocalRegion class to clear the entryExpiryTasks Map whenever
      the cancelAllEntryExpiryTasks method is invoked.
---
 ...titionedRegionClearWithExpirationDUnitTest.java | 516 +++++++++++++++++++++
 .../apache/geode/internal/cache/LocalRegion.java   |  11 +-
 .../geode/internal/cache/LocalRegionTest.java      |  22 +
 3 files changed, 548 insertions(+), 1 deletion(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
new file mode 100644
index 0000000..33301f4
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
@@ -0,0 +1,516 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.internal.cache;
+
+import static org.apache.geode.cache.ExpirationAction.DESTROY;
+import static org.apache.geode.cache.RegionShortcut.PARTITION;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_OVERFLOW;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_PERSISTENT;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_PERSISTENT_OVERFLOW;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT_OVERFLOW;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT_PERSISTENT;
+import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW;
+import static org.apache.geode.internal.util.ArrayUtils.asList;
+import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.IntStream;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import junitparams.naming.TestCaseName;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.geode.ForcedDisconnectException;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheWriter;
+import org.apache.geode.cache.CacheWriterException;
+import org.apache.geode.cache.ExpirationAttributes;
+import org.apache.geode.cache.PartitionAttributes;
+import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionEvent;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.partition.PartitionRegionHelper;
+import org.apache.geode.cache.util.CacheWriterAdapter;
+import org.apache.geode.distributed.DistributedSystemDisconnectedException;
+import org.apache.geode.distributed.internal.DMStats;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.distributed.internal.membership.api.MembershipManagerHelper;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.rules.CacheRule;
+import org.apache.geode.test.dunit.rules.DistributedDiskDirRule;
+import org.apache.geode.test.dunit.rules.DistributedRule;
+
+/**
+ * Tests to verify that {@link PartitionedRegion#clear()} cancels all remaining expiration tasks
+ * on the {@link PartitionedRegion} once the operation is executed.
+ */
+@RunWith(JUnitParamsRunner.class)
+public class PartitionedRegionClearWithExpirationDUnitTest implements Serializable {
+  private static final Integer BUCKETS = 13;
+  private static final Integer EXPIRATION_TIME = 30;
+  private static final String REGION_NAME = "PartitionedRegion";
+
+  @Rule
+  public DistributedRule distributedRule = new DistributedRule(3);
+
+  @Rule
+  public CacheRule cacheRule = CacheRule.builder().createCacheInAll().build();
+
+  @Rule
+  public DistributedDiskDirRule distributedDiskDirRule = new DistributedDiskDirRule();
+
+  private VM accessor, server1, server2;
+
+  private enum TestVM {
+    ACCESSOR(0), SERVER1(1), SERVER2(2);
+
+    final int vmNumber;
+
+    TestVM(int vmNumber) {
+      this.vmNumber = vmNumber;
+    }
+  }
+
+  @SuppressWarnings("unused")
+  static RegionShortcut[] regionTypes() {
+    return new RegionShortcut[] {
+        PARTITION,
+        PARTITION_OVERFLOW,
+        PARTITION_REDUNDANT,
+        PARTITION_REDUNDANT_OVERFLOW,
+
+        PARTITION_PERSISTENT,
+        PARTITION_PERSISTENT_OVERFLOW,
+        PARTITION_REDUNDANT_PERSISTENT,
+        PARTITION_REDUNDANT_PERSISTENT_OVERFLOW
+    };
+  }
+
+  @SuppressWarnings("unused")
+  static Object[] vmsAndRegionTypes() {
+    ArrayList<Object[]> parameters = new ArrayList<>();
+    RegionShortcut[] regionShortcuts = regionTypes();
+
+    Arrays.stream(regionShortcuts).forEach(regionShortcut -> {
+      parameters.add(new Object[] {TestVM.SERVER1, regionShortcut});
+      parameters.add(new Object[] {TestVM.ACCESSOR, regionShortcut});
+    });
+
+    return parameters.toArray();
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    server1 = getVM(TestVM.SERVER1.vmNumber);
+    server2 = getVM(TestVM.SERVER2.vmNumber);
+    accessor = getVM(TestVM.ACCESSOR.vmNumber);
+  }
+
+  private RegionShortcut getRegionAccessorShortcut(RegionShortcut dataStoreRegionShortcut) {
+    if (dataStoreRegionShortcut.isPersistent()) {
+      switch (dataStoreRegionShortcut) {
+        case PARTITION_PERSISTENT:
+          return PARTITION;
+        case PARTITION_PERSISTENT_OVERFLOW:
+          return PARTITION_OVERFLOW;
+        case PARTITION_REDUNDANT_PERSISTENT:
+          return PARTITION_REDUNDANT;
+        case PARTITION_REDUNDANT_PERSISTENT_OVERFLOW:
+          return PARTITION_REDUNDANT_OVERFLOW;
+      }
+    }
+
+    return dataStoreRegionShortcut;
+  }
+
+  private void initAccessor(RegionShortcut regionShortcut,
+      ExpirationAttributes expirationAttributes) {
+    RegionShortcut accessorShortcut = getRegionAccessorShortcut(regionShortcut);
+    PartitionAttributes<String, String> attributes =
+        new PartitionAttributesFactory<String, String>()
+            .setTotalNumBuckets(BUCKETS)
+            .setLocalMaxMemory(0)
+            .create();
+
+    cacheRule.getCache()
+        .<String, String>createRegionFactory(accessorShortcut)
+        .setPartitionAttributes(attributes)
+        .setEntryTimeToLive(expirationAttributes)
+        .setEntryIdleTimeout(expirationAttributes)
+        .create(REGION_NAME);
+  }
+
+  private void initDataStore(RegionShortcut regionShortcut,
+      ExpirationAttributes expirationAttributes) {
+    PartitionAttributes<String, String> attributes =
+        new PartitionAttributesFactory<String, String>()
+            .setTotalNumBuckets(BUCKETS)
+            .create();
+
+    cacheRule.getCache()
+        .<String, String>createRegionFactory(regionShortcut)
+        .setPartitionAttributes(attributes)
+        .setEntryTimeToLive(expirationAttributes)
+        .setEntryIdleTimeout(expirationAttributes)
+        .create(REGION_NAME);
+
+    ExpiryTask.expiryTaskListener = new ExpirationListener();
+  }
+
+  private void parametrizedSetup(RegionShortcut regionShortcut,
+      ExpirationAttributes expirationAttributes) {
+    server1.invoke(() -> initDataStore(regionShortcut, expirationAttributes));
+    server2.invoke(() -> initDataStore(regionShortcut, expirationAttributes));
+    accessor.invoke(() -> initAccessor(regionShortcut, expirationAttributes));
+  }
+
+  private void waitForSilence() {
+    DMStats dmStats = cacheRule.getSystem().getDistributionManager().getStats();
+    PartitionedRegion region = (PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME);
+    PartitionedRegionStats partitionedRegionStats = region.getPrStats();
+
+    await().untilAsserted(() -> {
+      assertThat(dmStats.getReplyWaitsInProgress()).isEqualTo(0);
+      assertThat(partitionedRegionStats.getVolunteeringInProgress()).isEqualTo(0);
+      assertThat(partitionedRegionStats.getBucketCreatesInProgress()).isEqualTo(0);
+      assertThat(partitionedRegionStats.getPrimaryTransfersInProgress()).isEqualTo(0);
+      assertThat(partitionedRegionStats.getRebalanceBucketCreatesInProgress()).isEqualTo(0);
+      assertThat(partitionedRegionStats.getRebalancePrimaryTransfersInProgress()).isEqualTo(0);
+    });
+  }
+
+  /**
+   * Populates the region and verifies the data on the selected VMs.
+   */
+  private void populateRegion(VM feeder, int entryCount, List<VM> vms) {
+    feeder.invoke(() -> {
+      Region<String, String> region = cacheRule.getCache().getRegion(REGION_NAME);
+      IntStream.range(0, entryCount).forEach(i -> region.put(String.valueOf(i), "Value_" + i));
+    });
+
+    vms.forEach(vm -> vm.invoke(() -> {
+      waitForSilence();
+      Region<String, String> region = cacheRule.getCache().getRegion(REGION_NAME);
+
+      IntStream.range(0, entryCount)
+          .forEach(i -> assertThat(region.get(String.valueOf(i))).isEqualTo("Value_" + i));
+    }));
+  }
+
+  /**
+   * Asserts that the region is empty on requested VMs.
+   */
+  private void assertRegionIsEmpty(List<VM> vms) {
+    vms.forEach(vm -> vm.invoke(() -> {
+      waitForSilence();
+      PartitionedRegion region = (PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME);
+
+      assertThat(region.getLocalSize()).isEqualTo(0);
+    }));
+  }
+
+  /**
+   * Asserts that the region data is consistent across buckets.
+   */
+  private void assertRegionBucketsConsistency() throws ForceReattemptException {
+    waitForSilence();
+    List<BucketDump> bucketDumps;
+    PartitionedRegion region = (PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME);
+    // Redundant copies + 1 primary.
+    int expectedCopies = region.getRedundantCopies() + 1;
+
+    for (int bucketId = 0; bucketId < BUCKETS; bucketId++) {
+      bucketDumps = region.getAllBucketEntries(bucketId);
+      assertThat(bucketDumps.size()).as("Bucket " + bucketId + " should have " + expectedCopies
+          + " copies, but has " + bucketDumps.size()).isEqualTo(expectedCopies);
+
+      // Check that all copies of the bucket have the same data.
+      if (bucketDumps.size() > 1) {
+        BucketDump firstDump = bucketDumps.get(0);
+
+        for (int j = 1; j < bucketDumps.size(); j++) {
+          BucketDump otherDump = bucketDumps.get(j);
+          assertThat(otherDump.getValues())
+              .as("Values for bucket " + bucketId + " on member " + otherDump.getMember()
+                  + " are not consistent with member " + firstDump.getMember())
+              .isEqualTo(firstDump.getValues());
+          assertThat(otherDump.getVersions())
+              .as("Versions for bucket " + bucketId + " on member " + otherDump.getMember()
+                  + " are not consistent with member " + firstDump.getMember())
+              .isEqualTo(firstDump.getVersions());
+        }
+      }
+    }
+  }
+
+  /**
+   * Register the MemberKiller CacheWriter on the given vms.
+   */
+  private void registerVMKillerAsCacheWriter(List<VM> vmsToBounce) {
+    vmsToBounce.forEach(vm -> vm.invoke(() -> {
+      Region<String, String> region = cacheRule.getCache().getRegion(REGION_NAME);
+      region.getAttributesMutator().setCacheWriter(new MemberKiller());
+    }));
+  }
+
+  /**
+   * The test does the following (clear coordinator and region type are parametrized):
+   * - Populates the Partition Region (entries have expiration).
+   * - Verifies that the entries are synchronized on all members.
+   * - Clears the Partition Region once.
+   * - Asserts that, after the clear is finished:
+   * . No expiration tasks were executed.
+   * . All expiration tasks were cancelled.
+   * . Map of expiry tasks per bucket is empty.
+   * . The Partition Region is empty on all members.
+   */
+  @Test
+  @Parameters(method = "vmsAndRegionTypes")
+  @TestCaseName("[{index}] {method}(Coordinator:{0}, RegionType:{1})")
+  public void clearShouldRemoveRegisteredExpirationTasks(TestVM coordinatorVM,
+      RegionShortcut regionShortcut) {
+    final int entries = 500;
+    int expirationTime = (int) GeodeAwaitility.getTimeout().getValueInMS() / 1000;
+    parametrizedSetup(regionShortcut, new ExpirationAttributes(expirationTime, DESTROY));
+    populateRegion(accessor, entries, asList(accessor, server1, server2));
+
+    // Clear the region.
+    getVM(coordinatorVM.vmNumber).invoke(() -> {
+      Cache cache = cacheRule.getCache();
+      cache.getRegion(REGION_NAME).clear();
+    });
+
+    // Assert all expiration tasks were cancelled and none were executed.
+    asList(server1, server2).forEach(vm -> vm.invoke(() -> {
+      ExpirationListener listener = (ExpirationListener) EntryExpiryTask.expiryTaskListener;
+      assertThat(listener.tasksRan.get()).isEqualTo(0);
+      assertThat(listener.tasksCanceled.get()).isEqualTo(listener.tasksScheduled.get());
+
+      PartitionedRegionDataStore dataStore =
+          ((PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME)).getDataStore();
+      Set<BucketRegion> bucketRegions = dataStore.getAllLocalBucketRegions();
+      bucketRegions
+          .forEach(bucketRegion -> assertThat(bucketRegion.entryExpiryTasks.isEmpty()).isTrue());
+    }));
+
+    // Assert Region Buckets are consistent and region is empty,
+    accessor.invoke(this::assertRegionBucketsConsistency);
+    assertRegionIsEmpty(asList(accessor, server1, server1));
+  }
+
+  /**
+   * The test does the following (region type is parametrized):
+   * - Populates the Partition Region (entries have expiration).
+   * - Verifies that the entries are synchronized on all members.
+   * - Sets the {@link MemberKiller} as a {@link CacheWriter} to stop the coordinator VM while the
+   * clear is in progress.
+   * - Clears the Partition Region (at this point the coordinator is restarted).
+   * - Asserts that, after the clear is finished and the expiration time is reached:
+   * . No expiration tasks were cancelled.
+   * . All entries were removed due to the expiration.
+   * . The Partition Region Buckets are consistent on all members.
+   */
+  @Test
+  @Parameters(method = "regionTypes")
+  @TestCaseName("[{index}] {method}(RegionType:{0})")
+  public void clearShouldFailWhenCoordinatorMemberIsBouncedAndExpirationTasksShouldSurvive(
+      RegionShortcut regionShortcut) {
+    final int entries = 1000;
+    ExpirationAttributes expirationAttributes = new ExpirationAttributes(EXPIRATION_TIME, DESTROY);
+    parametrizedSetup(regionShortcut, expirationAttributes);
+    populateRegion(accessor, entries, asList(accessor, server1, server2));
+    registerVMKillerAsCacheWriter(Collections.singletonList(server1));
+
+    // Clear the region (it should fail).
+    server1.invoke(() -> {
+      Region<String, String> region = cacheRule.getCache().getRegion(REGION_NAME);
+      assertThatThrownBy(region::clear)
+          .isInstanceOf(DistributedSystemDisconnectedException.class)
+          .hasCauseInstanceOf(ForcedDisconnectException.class);
+    });
+
+    // Wait for member to get back online and assign all buckets.
+    server1.invoke(() -> {
+      cacheRule.createCache();
+      initDataStore(regionShortcut, expirationAttributes);
+      await().untilAsserted(
+          () -> assertThat(InternalDistributedSystem.getConnectedInstance()).isNotNull());
+      PartitionRegionHelper.assignBucketsToPartitions(cacheRule.getCache().getRegion(REGION_NAME));
+    });
+
+    // Wait until all expiration tasks are executed.
+    asList(server1, server2).forEach(vm -> vm.invoke(() -> {
+      PartitionedRegionDataStore dataStore =
+          ((PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME)).getDataStore();
+      Set<BucketRegion> bucketRegions = dataStore.getAllLocalBucketRegions();
+      bucketRegions.forEach(bucketRegion -> await()
+          .untilAsserted(() -> assertThat(bucketRegion.entryExpiryTasks.isEmpty()).isTrue()));
+    }));
+
+    // At this point the entries should be either invalidated or destroyed (expiration tasks ran).
+    asList(accessor, server1, server2).forEach(vm -> vm.invoke(() -> {
+      Region<String, String> region = cacheRule.getCache().getRegion(REGION_NAME);
+      IntStream.range(0, entries).forEach(i -> {
+        String key = String.valueOf(i);
+        assertThat(region.get(key)).isNull();
+      });
+    }));
+
+    // Assert Region Buckets are consistent.
+    accessor.invoke(this::assertRegionBucketsConsistency);
+  }
+
+  /**
+   * The test does the following (clear coordinator and region type are parametrized):
+   * - Populates the Partition Region (entries have expiration).
+   * - Verifies that the entries are synchronized on all members.
+   * - Sets the {@link MemberKiller} as a {@link CacheWriter} to stop a non-coordinator VM while the
+   * clear is in progress (the member has primary buckets, though, so participates on
+   * the clear operation).
+   * - Clears the Partition Region (at this point the non-coordinator is restarted).
+   * - Asserts that, after the clear is finished:
+   * . No expiration tasks were executed on the non-restarted members.
+   * . All expiration tasks were cancelled on the non-restarted members.
+   * . Map of expiry tasks per bucket is empty on the non-restarted members.
+   * . All expiration tasks were executed and all expired on the restarted members.
+   * . The Partition Region is empty and buckets are consistent across all members.
+   */
+  @Test
+  @Parameters(method = "vmsAndRegionTypes")
+  @TestCaseName("[{index}] {method}(Coordinator:{0}, RegionType:{1})")
+  public void clearShouldSucceedAndRemoveRegisteredExpirationTasksWhenNonCoordinatorMemberIsBounced(
+      TestVM coordinatorVM, RegionShortcut regionShortcut) {
+    final int entries = 1500;
+    ExpirationAttributes expirationAttributes = new ExpirationAttributes(EXPIRATION_TIME, DESTROY);
+    parametrizedSetup(regionShortcut, expirationAttributes);
+    registerVMKillerAsCacheWriter(Collections.singletonList(server2));
+    populateRegion(accessor, entries, asList(accessor, server1, server2));
+
+    // Clear the region.
+    getVM(coordinatorVM.vmNumber).invoke(() -> {
+      Cache cache = cacheRule.getCache();
+      cache.getRegion(REGION_NAME).clear();
+    });
+
+    // Wait for member to get back online and assign buckets.
+    server2.invoke(() -> {
+      cacheRule.createCache();
+      initDataStore(regionShortcut, expirationAttributes);
+      await().untilAsserted(
+          () -> assertThat(InternalDistributedSystem.getConnectedInstance()).isNotNull());
+      PartitionRegionHelper.assignBucketsToPartitions(cacheRule.getCache().getRegion(REGION_NAME));
+    });
+
+    // Assert all expiration tasks were cancelled and none were executed (surviving members).
+    server1.invoke(() -> {
+      PartitionedRegionDataStore dataStore =
+          ((PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME)).getDataStore();
+      Set<BucketRegion> bucketRegions = dataStore.getAllLocalBucketRegions();
+      bucketRegions
+          .forEach(bucketRegion -> assertThat(bucketRegion.entryExpiryTasks.isEmpty()).isTrue());
+
+      ExpirationListener listener = (ExpirationListener) EntryExpiryTask.expiryTaskListener;
+      assertThat(listener.tasksRan.get()).isEqualTo(0);
+      assertThat(listener.tasksCanceled.get()).isEqualTo(listener.tasksScheduled.get());
+    });
+
+    // Assert all expiration tasks were expired as the region is empty (restarted member).
+    server2.invoke(() -> {
+      PartitionedRegionDataStore dataStore =
+          ((PartitionedRegion) cacheRule.getCache().getRegion(REGION_NAME)).getDataStore();
+      Set<BucketRegion> bucketRegions = dataStore.getAllLocalBucketRegions();
+
+      // During restart, the member loads the region from disk and automatically registers
+      // expiration tasks for each entry. After GII, however, the region is empty due to the
+      // clear operation and the tasks will just expire as there are no entries.
+      bucketRegions.forEach(bucketRegion -> await()
+          .untilAsserted(() -> assertThat(bucketRegion.entryExpiryTasks.isEmpty()).isTrue()));
+
+      ExpirationListener listener = (ExpirationListener) EntryExpiryTask.expiryTaskListener;
+      assertThat(listener.tasksExpired.get()).isEqualTo(listener.tasksRan.get());
+    });
+
+    // Assert Region Buckets are consistent and region is empty,
+    accessor.invoke(this::assertRegionBucketsConsistency);
+    assertRegionIsEmpty(asList(accessor, server1, server1));
+  }
+
+  /**
+   * Tracks expiration tasks lifecycle.
+   */
+  public static class ExpirationListener implements ExpiryTask.ExpiryTaskListener {
+    final AtomicInteger tasksRan = new AtomicInteger(0);
+    final AtomicInteger tasksExpired = new AtomicInteger(0);
+    final AtomicInteger tasksCanceled = new AtomicInteger(0);
+    final AtomicInteger tasksScheduled = new AtomicInteger(0);
+
+    @Override
+    public void afterSchedule(ExpiryTask et) {
+      tasksScheduled.incrementAndGet();
+    }
+
+    @Override
+    public void afterTaskRan(ExpiryTask et) {
+      tasksRan.incrementAndGet();
+    }
+
+    @Override
+    public void afterReschedule(ExpiryTask et) {}
+
+    @Override
+    public void afterExpire(ExpiryTask et) {
+      tasksExpired.incrementAndGet();
+    }
+
+    @Override
+    public void afterCancel(ExpiryTask et) {
+      tasksCanceled.incrementAndGet();
+    }
+  }
+
+  /**
+   * Shutdowns a member while the clear operation is in progress.
+   * The writer is only installed on the member the test wants to shutdown, doesn't matter whether
+   * it's the clear coordinator or another member holding primary buckets.
+   */
+  public static class MemberKiller extends CacheWriterAdapter<String, String> {
+
+    @Override
+    public synchronized void beforeRegionClear(RegionEvent<String, String> event)
+        throws CacheWriterException {
+      InternalDistributedSystem.getConnectedInstance().stopReconnectingNoDisconnect();
+      MembershipManagerHelper.crashDistributedSystem(
+          InternalDistributedSystem.getConnectedInstance());
+      await().untilAsserted(
+          () -> assertThat(InternalDistributedSystem.getConnectedInstance()).isNull());
+    }
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
index 3580f72..dcf35fa 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
@@ -325,6 +325,10 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
    */
   private int txRefCount;
 
+  @VisibleForTesting
+  final ConcurrentHashMap<RegionEntry, EntryExpiryTask> entryExpiryTasks =
+      new ConcurrentHashMap<>();
+
   private volatile boolean regionInvalid;
 
   /**
@@ -7967,7 +7971,8 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
     }
   }
 
-  private void cancelAllEntryExpiryTasks() {
+  @VisibleForTesting
+  void cancelAllEntryExpiryTasks() {
     // This method gets called during LocalRegion construction
     // in which case the final entryExpiryTasks field can still be null
     if (entryExpiryTasks.isEmpty()) {
@@ -7979,6 +7984,10 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
       task.cancel();
       doPurge = true;
     }
+
+    // Clear the map after canceling each expiry task.
+    entryExpiryTasks.clear();
+
     if (doPurge) {
       // do a force to not leave any refs to this region
       cache.getExpirationScheduler().forcePurge();
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/LocalRegionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/LocalRegionTest.java
index d695565..3b7e481 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/LocalRegionTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/LocalRegionTest.java
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -222,4 +223,25 @@ public class LocalRegionTest {
     assertThat(result.get("key1")).isNull();
     assertThat(result.get("key2")).isEqualTo("value2");
   }
+
+  @Test
+  public void cancelAllEntryExpiryTasksShouldClearMapOfExpiryTasks() {
+    when(cache.getExpirationScheduler()).thenReturn(mock(ExpirationScheduler.class));
+    LocalRegion region =
+        spy(new LocalRegion("region", regionAttributes, null, cache, internalRegionArguments,
+            internalDataView, regionMapConstructor, serverRegionProxyConstructor, entryEventFactory,
+            poolFinder, regionPerfStatsFactory, disabledClock()));
+
+    RegionEntry regionEntry1 = mock(RegionEntry.class);
+    RegionEntry regionEntry2 = mock(RegionEntry.class);
+    EntryExpiryTask entryExpiryTask1 = spy(new EntryExpiryTask(region, regionEntry1));
+    EntryExpiryTask entryExpiryTask2 = spy(new EntryExpiryTask(region, regionEntry2));
+    region.entryExpiryTasks.put(regionEntry1, entryExpiryTask1);
+    region.entryExpiryTasks.put(regionEntry2, entryExpiryTask2);
+
+    region.cancelAllEntryExpiryTasks();
+    assertThat(region.entryExpiryTasks).isEmpty();
+    verify(entryExpiryTask1, times(1)).cancel();
+    verify(entryExpiryTask2, times(1)).cancel();
+  }
 }


[geode] 04/11: GEODE-7912: cacheWriter should be triggered when PR.clear (#4882)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 653b44d209461b180d827408382f8050c77cde73
Author: Xiaojian Zhou <ge...@users.noreply.github.com>
AuthorDate: Mon Mar 30 19:34:35 2020 -0700

    GEODE-7912: cacheWriter should be triggered when PR.clear (#4882)
    
    
            Co-authored-by: Anil <ag...@pivotal.io>
            Co-authored-by: Xiaojian Zhou <gz...@pivotal.io>
---
 .../cache/PartitionedRegionClearDUnitTest.java     | 228 +++++++++++++++++----
 .../apache/geode/internal/cache/LocalRegion.java   |   4 +-
 .../geode/internal/cache/PartitionedRegion.java    |  56 +++--
 3 files changed, 223 insertions(+), 65 deletions(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
index fb2a81b..a5a22b9 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
@@ -20,6 +20,7 @@ import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getClientCach
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.Serializable;
+import java.util.HashMap;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.IntStream;
@@ -30,13 +31,15 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import org.apache.geode.cache.CacheWriterException;
 import org.apache.geode.cache.InterestResultPolicy;
 import org.apache.geode.cache.PartitionAttributesFactory;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.RegionEvent;
+import org.apache.geode.cache.RegionFactory;
 import org.apache.geode.cache.RegionShortcut;
 import org.apache.geode.cache.client.ClientRegionShortcut;
-import org.apache.geode.cache.util.CacheListenerAdapter;
+import org.apache.geode.cache.util.CacheWriterAdapter;
 import org.apache.geode.test.dunit.SerializableCallableIF;
 import org.apache.geode.test.dunit.rules.ClientVM;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
@@ -68,12 +71,6 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         c -> c.withPoolSubscription(true).withLocatorConnection((locatorPort)));
     client2 = cluster.startClientVM(6,
         c -> c.withPoolSubscription(true).withLocatorConnection((locatorPort)));
-    dataStore1.invoke(this::initDataStore);
-    dataStore2.invoke(this::initDataStore);
-    dataStore3.invoke(this::initDataStore);
-    accessor.invoke(this::initAccessor);
-    client1.invoke(this::initClientCache);
-    client2.invoke(this::initClientCache);
   }
 
   protected RegionShortcut getRegionShortCut() {
@@ -104,14 +101,18 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
     region.registerInterestForAllKeys(InterestResultPolicy.KEYS);
   }
 
-  private void initDataStore() {
-    getCache().createRegionFactory(getRegionShortCut())
-        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create())
-        .addCacheListener(new CountingCacheListener())
-        .create(REGION_NAME);
+  private void initDataStore(boolean withWriter) {
+    RegionFactory factory = getCache().createRegionFactory(getRegionShortCut())
+        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create());
+    if (withWriter) {
+      factory.setCacheWriter(new CountingCacheWriter());
+    }
+    factory.create(REGION_NAME);
+    clearsByRegion = new HashMap<>();
+    destroysByRegion = new HashMap<>();
   }
 
-  private void initAccessor() {
+  private void initAccessor(boolean withWriter) {
     RegionShortcut shortcut = getRegionShortCut();
     if (shortcut.isPersistent()) {
       if (shortcut == RegionShortcut.PARTITION_PERSISTENT) {
@@ -126,12 +127,16 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         fail("Wrong region type:" + shortcut);
       }
     }
-    getCache().createRegionFactory(shortcut)
+    RegionFactory factory = getCache().createRegionFactory(shortcut)
         .setPartitionAttributes(
             new PartitionAttributesFactory().setTotalNumBuckets(10).setLocalMaxMemory(0).create())
-        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create())
-        .addCacheListener(new CountingCacheListener())
-        .create(REGION_NAME);
+        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create());
+    if (withWriter) {
+      factory.setCacheWriter(new CountingCacheWriter());
+    }
+    factory.create(REGION_NAME);
+    clearsByRegion = new HashMap<>();
+    destroysByRegion = new HashMap<>();
   }
 
   private void feed(boolean isClient) {
@@ -152,45 +157,148 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
     // client2.invoke(()->verifyRegionSize(true, expectedNum));
   }
 
-  private void verifyCacheListenerTriggerCount(MemberVM serverVM) {
-    SerializableCallableIF<Integer> getListenerTriggerCount = () -> {
-      CountingCacheListener countingCacheListener =
-          (CountingCacheListener) getRegion(false).getAttributes()
-              .getCacheListeners()[0];
-      return countingCacheListener.getClears();
-    };
+  SerializableCallableIF<Integer> getWriterClears = () -> {
+    int clears =
+        clearsByRegion.get(REGION_NAME) == null ? 0 : clearsByRegion.get(REGION_NAME).get();
+    return clears;
+  };
 
-    int count = accessor.invoke(getListenerTriggerCount)
-        + dataStore1.invoke(getListenerTriggerCount)
-        + dataStore2.invoke(getListenerTriggerCount)
-        + dataStore3.invoke(getListenerTriggerCount);
-    assertThat(count).isEqualTo(1);
+  SerializableCallableIF<Integer> getWriterDestroys = () -> {
+    int destroys =
+        destroysByRegion.get(REGION_NAME) == null ? 0 : destroysByRegion.get(REGION_NAME).get();
+    return destroys;
+  };
 
-    if (serverVM != null) {
-      assertThat(serverVM.invoke(getListenerTriggerCount)).isEqualTo(1);
-    }
+  void configureServers(boolean dataStoreWithWriter, boolean accessorWithWriter) {
+    dataStore1.invoke(() -> initDataStore(dataStoreWithWriter));
+    dataStore2.invoke(() -> initDataStore(dataStoreWithWriter));
+    dataStore3.invoke(() -> initDataStore(dataStoreWithWriter));
+    accessor.invoke(() -> initAccessor(accessorWithWriter));
+    // make sure only datastore3 has cacheWriter
+    dataStore1.invoke(() -> {
+      Region region = getRegion(false);
+      region.getAttributesMutator().setCacheWriter(null);
+    });
+    dataStore2.invoke(() -> {
+      Region region = getRegion(false);
+      region.getAttributesMutator().setCacheWriter(null);
+    });
+  }
+
+  @Test
+  public void normalClearFromDataStoreWithWriterOnDataStore() {
+    configureServers(true, true);
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+    dataStore3.invoke(() -> getRegion(false).clear());
+    verifyServerRegionSize(0);
+
+    // do the region destroy to compare that the same callbacks will be triggered
+    dataStore3.invoke(() -> {
+      Region region = getRegion(false);
+      region.destroyRegion();
+    });
+
+    assertThat(dataStore1.invoke(getWriterDestroys)).isEqualTo(dataStore1.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore2.invoke(getWriterDestroys)).isEqualTo(dataStore2.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore3.invoke(getWriterDestroys)).isEqualTo(dataStore3.invoke(getWriterClears))
+        .isEqualTo(1);
+    assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
+        .isEqualTo(0);
   }
 
   @Test
-  public void normalClearFromDataStore() {
+  public void normalClearFromDataStoreWithoutWriterOnDataStore() {
+    configureServers(false, true);
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
     accessor.invoke(() -> feed(false));
     verifyServerRegionSize(NUM_ENTRIES);
     dataStore1.invoke(() -> getRegion(false).clear());
     verifyServerRegionSize(0);
-    verifyCacheListenerTriggerCount(dataStore1);
+
+    // do the region destroy to compare that the same callbacks will be triggered
+    dataStore1.invoke(() -> {
+      Region region = getRegion(false);
+      region.destroyRegion();
+    });
+
+    assertThat(dataStore1.invoke(getWriterDestroys)).isEqualTo(dataStore1.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore2.invoke(getWriterDestroys)).isEqualTo(dataStore2.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore3.invoke(getWriterDestroys)).isEqualTo(dataStore3.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
+        .isEqualTo(1);
   }
 
   @Test
-  public void normalClearFromAccessor() {
+  public void normalClearFromAccessorWithWriterOnDataStore() {
+    configureServers(true, true);
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
     accessor.invoke(() -> feed(false));
     verifyServerRegionSize(NUM_ENTRIES);
     accessor.invoke(() -> getRegion(false).clear());
     verifyServerRegionSize(0);
-    verifyCacheListenerTriggerCount(accessor);
+
+    // do the region destroy to compare that the same callbacks will be triggered
+    accessor.invoke(() -> {
+      Region region = getRegion(false);
+      region.destroyRegion();
+    });
+
+    assertThat(dataStore1.invoke(getWriterDestroys)).isEqualTo(dataStore1.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore2.invoke(getWriterDestroys)).isEqualTo(dataStore2.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore3.invoke(getWriterDestroys)).isEqualTo(dataStore3.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
+        .isEqualTo(1);
+  }
+
+  @Test
+  public void normalClearFromAccessorWithoutWriterButWithWriterOnDataStore() {
+    configureServers(true, false);
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+    accessor.invoke(() -> getRegion(false).clear());
+    verifyServerRegionSize(0);
+
+    // do the region destroy to compare that the same callbacks will be triggered
+    accessor.invoke(() -> {
+      Region region = getRegion(false);
+      region.destroyRegion();
+    });
+
+    assertThat(dataStore1.invoke(getWriterDestroys)).isEqualTo(dataStore1.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore2.invoke(getWriterDestroys)).isEqualTo(dataStore2.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore3.invoke(getWriterDestroys)).isEqualTo(dataStore3.invoke(getWriterClears))
+        .isEqualTo(1);
+    assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
+        .isEqualTo(0);
   }
 
   @Test
   public void normalClearFromClient() {
+    configureServers(true, false);
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
     client1.invoke(() -> feed(true));
     verifyClientRegionSize(NUM_ENTRIES);
     verifyServerRegionSize(NUM_ENTRIES);
@@ -198,21 +306,53 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
     client1.invoke(() -> getRegion(true).clear());
     verifyServerRegionSize(0);
     verifyClientRegionSize(0);
-    verifyCacheListenerTriggerCount(null);
+
+    // do the region destroy to compare that the same callbacks will be triggered
+    client1.invoke(() -> {
+      Region region = getRegion(true);
+      region.destroyRegion();
+    });
+
+    assertThat(dataStore1.invoke(getWriterDestroys)).isEqualTo(dataStore1.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore2.invoke(getWriterDestroys)).isEqualTo(dataStore2.invoke(getWriterClears))
+        .isEqualTo(0);
+    assertThat(dataStore3.invoke(getWriterDestroys)).isEqualTo(dataStore3.invoke(getWriterClears))
+        .isEqualTo(1);
+    assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
+        .isEqualTo(0);
   }
 
-  private static class CountingCacheListener extends CacheListenerAdapter {
-    private final AtomicInteger clears = new AtomicInteger();
+  public static HashMap<String, AtomicInteger> clearsByRegion = new HashMap<>();
+  public static HashMap<String, AtomicInteger> destroysByRegion = new HashMap<>();
 
+  private static class CountingCacheWriter extends CacheWriterAdapter {
     @Override
-    public void afterRegionClear(RegionEvent event) {
+    public void beforeRegionClear(RegionEvent event) throws CacheWriterException {
       Region region = event.getRegion();
-      logger.info("Region " + region.getFullPath() + " is cleared.");
-      clears.incrementAndGet();
+      AtomicInteger clears = clearsByRegion.get(region.getName());
+      if (clears == null) {
+        clears = new AtomicInteger(1);
+        clearsByRegion.put(region.getName(), clears);
+      } else {
+        clears.incrementAndGet();
+      }
+      logger
+          .info("Region " + region.getName() + " will be cleared, clear count is:" + clears.get());
     }
 
-    int getClears() {
-      return clears.get();
+    @Override
+    public void beforeRegionDestroy(RegionEvent event) throws CacheWriterException {
+      Region region = event.getRegion();
+      AtomicInteger destroys = destroysByRegion.get(region.getName());
+      if (destroys == null) {
+        destroys = new AtomicInteger(1);
+        destroysByRegion.put(region.getName(), destroys);
+      } else {
+        destroys.incrementAndGet();
+      }
+      logger.info(
+          "Region " + region.getName() + " will be destroyed, destroy count is:" + destroys.get());
     }
   }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
index a27e058..3580f72 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
@@ -3000,7 +3000,7 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
   /**
    * @since GemFire 5.7
    */
-  private void serverRegionClear(RegionEventImpl regionEvent) {
+  protected void serverRegionClear(RegionEventImpl regionEvent) {
     if (regionEvent.getOperation().isDistributed()) {
       ServerRegionProxy mySRP = getServerProxy();
       if (mySRP != null) {
@@ -3121,7 +3121,7 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
     return result;
   }
 
-  private void cacheWriteBeforeRegionClear(RegionEventImpl event)
+  void cacheWriteBeforeRegionClear(RegionEventImpl event)
       throws CacheWriterException, TimeoutException {
     // copy into local var to prevent race condition
     CacheWriter writer = basicGetWriter();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
index 7b5a2c7..f0b2992 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
@@ -2188,6 +2188,9 @@ public class PartitionedRegion extends LocalRegion
           throw cache.getCacheClosedException("Cache is shutting down");
         }
 
+        // do cacheWrite
+        cacheWriteBeforeRegionClear(regionEvent);
+
         // create ClearPRMessage per bucket
         List<ClearPRMessage> clearMsgList = createClearPRMessages(regionEvent.getEventId());
         for (ClearPRMessage clearPRMessage : clearMsgList) {
@@ -4455,6 +4458,26 @@ public class PartitionedRegion extends LocalRegion
     return null;
   }
 
+  boolean triggerWriter(RegionEventImpl event, SearchLoadAndWriteProcessor processor, int paction,
+      String theKey) {
+    CacheWriter localWriter = basicGetWriter();
+    Set netWriteRecipients = localWriter == null ? this.distAdvisor.adviseNetWrite() : null;
+
+    if (localWriter == null && (netWriteRecipients == null || netWriteRecipients.isEmpty())) {
+      return false;
+    }
+
+    final long start = getCachePerfStats().startCacheWriterCall();
+    try {
+      processor.initialize(this, theKey, null);
+      processor.doNetWrite(event, netWriteRecipients, localWriter, paction);
+      processor.release();
+    } finally {
+      getCachePerfStats().endCacheWriterCall(start);
+    }
+    return true;
+  }
+
   /**
    * This invokes a cache writer before a destroy operation. Although it has the same method
    * signature as the method in LocalRegion, it is invoked in a different code path. LocalRegion
@@ -4464,31 +4487,26 @@ public class PartitionedRegion extends LocalRegion
   @Override
   boolean cacheWriteBeforeRegionDestroy(RegionEventImpl event)
       throws CacheWriterException, TimeoutException {
-
     if (event.getOperation().isDistributed()) {
       serverRegionDestroy(event);
-      CacheWriter localWriter = basicGetWriter();
-      Set netWriteRecipients = localWriter == null ? this.distAdvisor.adviseNetWrite() : null;
-
-      if (localWriter == null && (netWriteRecipients == null || netWriteRecipients.isEmpty())) {
-        return false;
-      }
-
-      final long start = getCachePerfStats().startCacheWriterCall();
-      try {
-        SearchLoadAndWriteProcessor processor = SearchLoadAndWriteProcessor.getProcessor();
-        processor.initialize(this, "preDestroyRegion", null);
-        processor.doNetWrite(event, netWriteRecipients, localWriter,
-            SearchLoadAndWriteProcessor.BEFOREREGIONDESTROY);
-        processor.release();
-      } finally {
-        getCachePerfStats().endCacheWriterCall(start);
-      }
-      return true;
+      SearchLoadAndWriteProcessor processor = SearchLoadAndWriteProcessor.getProcessor();
+      return triggerWriter(event, processor, SearchLoadAndWriteProcessor.BEFOREREGIONDESTROY,
+          "preDestroyRegion");
     }
     return false;
   }
 
+  @Override
+  void cacheWriteBeforeRegionClear(RegionEventImpl event)
+      throws CacheWriterException, TimeoutException {
+    if (event.getOperation().isDistributed()) {
+      serverRegionClear(event);
+      SearchLoadAndWriteProcessor processor = SearchLoadAndWriteProcessor.getProcessor();
+      triggerWriter(event, processor, SearchLoadAndWriteProcessor.BEFOREREGIONCLEAR,
+          "preClearRegion");
+    }
+  }
+
   /**
    * Test Method: Get the DistributedMember identifier for the vm containing a key
    *


[geode] 08/11: GEODE-7676: Conversion of duration to seconds.

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit df4cb91aeefacc86e19f770948be7d3e080f4c2b
Author: Nabarun Nag <na...@cs.wisc.edu>
AuthorDate: Mon May 11 12:24:16 2020 -0700

    GEODE-7676: Conversion of duration to seconds.
---
 .../internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
index 33301f4..7f3dff9 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
@@ -298,7 +298,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
   public void clearShouldRemoveRegisteredExpirationTasks(TestVM coordinatorVM,
       RegionShortcut regionShortcut) {
     final int entries = 500;
-    int expirationTime = (int) GeodeAwaitility.getTimeout().getValueInMS() / 1000;
+    int expirationTime = (int) GeodeAwaitility.getTimeout().getSeconds();
     parametrizedSetup(regionShortcut, new ExpirationAttributes(expirationTime, DESTROY));
     populateRegion(accessor, entries, asList(accessor, server1, server2));
 


[geode] 05/11: GEODE-7983: Clear region writer callbacks should not be invoked for bucket regions (#4954)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 9a6cc48ea68b5a467805b4c60d1d80f7de6aea26
Author: Xiaojian Zhou <ge...@users.noreply.github.com>
AuthorDate: Tue Apr 14 10:50:21 2020 -0700

    GEODE-7983: Clear region writer callbacks should not be invoked for bucket regions (#4954)
---
 .../cache/PartitionedRegionClearDUnitTest.java     | 44 +++++++++++++++++++++-
 .../internal/cache/partitioned/ClearPRMessage.java |  2 +-
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
index a5a22b9..e2e04eb 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
@@ -47,6 +47,7 @@ import org.apache.geode.test.dunit.rules.MemberVM;
 
 public class PartitionedRegionClearDUnitTest implements Serializable {
   protected static final String REGION_NAME = "testPR";
+  protected static final int TOTAL_BUCKET_NUM = 10;
   protected static final int NUM_ENTRIES = 1000;
 
   protected int locatorPort;
@@ -103,7 +104,8 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
 
   private void initDataStore(boolean withWriter) {
     RegionFactory factory = getCache().createRegionFactory(getRegionShortCut())
-        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create());
+        .setPartitionAttributes(
+            new PartitionAttributesFactory().setTotalNumBuckets(TOTAL_BUCKET_NUM).create());
     if (withWriter) {
       factory.setCacheWriter(new CountingCacheWriter());
     }
@@ -169,6 +171,26 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
     return destroys;
   };
 
+  SerializableCallableIF<Integer> getBucketRegionWriterClears = () -> {
+    int clears = 0;
+    for (int i = 0; i < TOTAL_BUCKET_NUM; i++) {
+      String bucketRegionName = "_B__" + REGION_NAME + "_" + i;
+      clears += clearsByRegion.get(bucketRegionName) == null ? 0
+          : clearsByRegion.get(bucketRegionName).get();
+    }
+    return clears;
+  };
+
+  SerializableCallableIF<Integer> getBucketRegionWriterDestroys = () -> {
+    int destroys = 0;
+    for (int i = 0; i < TOTAL_BUCKET_NUM; i++) {
+      String bucketRegionName = "_B__" + REGION_NAME + "_" + i;
+      destroys += destroysByRegion.get(bucketRegionName) == null ? 0
+          : destroysByRegion.get(bucketRegionName).get();
+    }
+    return destroys;
+  };
+
   void configureServers(boolean dataStoreWithWriter, boolean accessorWithWriter) {
     dataStore1.invoke(() -> initDataStore(dataStoreWithWriter));
     dataStore2.invoke(() -> initDataStore(dataStoreWithWriter));
@@ -210,6 +232,10 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         .isEqualTo(1);
     assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
         .isEqualTo(0);
+
+    assertThat(dataStore3.invoke(getBucketRegionWriterDestroys))
+        .isEqualTo(dataStore3.invoke(getBucketRegionWriterClears))
+        .isEqualTo(0);
   }
 
   @Test
@@ -237,6 +263,10 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         .isEqualTo(0);
     assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
         .isEqualTo(1);
+
+    assertThat(accessor.invoke(getBucketRegionWriterDestroys))
+        .isEqualTo(accessor.invoke(getBucketRegionWriterClears))
+        .isEqualTo(0);
   }
 
   @Test
@@ -264,6 +294,10 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         .isEqualTo(0);
     assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
         .isEqualTo(1);
+
+    assertThat(accessor.invoke(getBucketRegionWriterDestroys))
+        .isEqualTo(accessor.invoke(getBucketRegionWriterClears))
+        .isEqualTo(0);
   }
 
   @Test
@@ -291,6 +325,10 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         .isEqualTo(1);
     assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
         .isEqualTo(0);
+
+    assertThat(dataStore3.invoke(getBucketRegionWriterDestroys))
+        .isEqualTo(dataStore3.invoke(getBucketRegionWriterClears))
+        .isEqualTo(0);
   }
 
   @Test
@@ -321,6 +359,10 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
         .isEqualTo(1);
     assertThat(accessor.invoke(getWriterDestroys)).isEqualTo(accessor.invoke(getWriterClears))
         .isEqualTo(0);
+
+    assertThat(dataStore3.invoke(getBucketRegionWriterDestroys))
+        .isEqualTo(dataStore3.invoke(getBucketRegionWriterClears))
+        .isEqualTo(0);
   }
 
   public static HashMap<String, AtomicInteger> clearsByRegion = new HashMap<>();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
index cc01920..2603b78 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
@@ -175,7 +175,7 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     try {
       RegionEventImpl regionEvent = new RegionEventImpl(bucketRegion, Operation.REGION_CLEAR, null,
           false, region.getMyId(), eventID);
-      bucketRegion.cmnClearRegion(regionEvent, true, true);
+      bucketRegion.cmnClearRegion(regionEvent, false, true);
     } catch (PartitionOfflineException poe) {
       logger.info(
           "All members holding data for bucket {} are offline, no more retries will be attempted",


[geode] 02/11: GEODE-7682: add PR.clear API (#4755)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 8f1612b1c472deae731a47a07c89226afcfaee0b
Author: Xiaojian Zhou <ge...@users.noreply.github.com>
AuthorDate: Thu Mar 5 23:46:36 2020 -0800

    GEODE-7682: add PR.clear  API (#4755)
    
    * GEODE-7683: introduce BR.cmnClearRegion
    
    Co-authored-by: Xiaojian Zhou <gz...@pivotal.io>
---
 .../cache/PartitionedRegionClearDUnitTest.java     | 218 +++++++++++++++++++++
 .../PartitionedRegionPersistentClearDUnitTest.java |  26 +++
 ...itionedRegionSingleNodeOperationsJUnitTest.java |  66 -------
 .../codeAnalysis/sanctionedDataSerializables.txt   |   4 +-
 .../org/apache/geode/internal/DSFIDFactory.java    |   3 +
 .../geode/internal/cache/DistributedRegion.java    |   9 -
 .../apache/geode/internal/cache/LocalRegion.java   |  10 +
 .../geode/internal/cache/PartitionedRegion.java    | 214 ++++++++++++++++++--
 .../geode/internal/cache/RegionEventImpl.java      |   5 +
 .../internal/cache/partitioned/ClearPRMessage.java | 166 +++++-----------
 .../cache/partitioned/ClearPRMessageTest.java      |  50 ++---
 11 files changed, 522 insertions(+), 249 deletions(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
new file mode 100644
index 0000000..fb2a81b
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.internal.cache;
+
+import static org.apache.geode.internal.Assert.fail;
+import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getCache;
+import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getClientCache;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.IntStream;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.cache.InterestResultPolicy;
+import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionEvent;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.util.CacheListenerAdapter;
+import org.apache.geode.test.dunit.SerializableCallableIF;
+import org.apache.geode.test.dunit.rules.ClientVM;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+public class PartitionedRegionClearDUnitTest implements Serializable {
+  protected static final String REGION_NAME = "testPR";
+  protected static final int NUM_ENTRIES = 1000;
+
+  protected int locatorPort;
+  protected MemberVM locator;
+  protected MemberVM dataStore1, dataStore2, dataStore3, accessor;
+  protected ClientVM client1, client2;
+
+  private static final Logger logger = LogManager.getLogger();
+
+  @Rule
+  public ClusterStartupRule cluster = new ClusterStartupRule(7);
+
+  @Before
+  public void setUp() throws Exception {
+    locator = cluster.startLocatorVM(0);
+    locatorPort = locator.getPort();
+    dataStore1 = cluster.startServerVM(1, getProperties(), locatorPort);
+    dataStore2 = cluster.startServerVM(2, getProperties(), locatorPort);
+    dataStore3 = cluster.startServerVM(3, getProperties(), locatorPort);
+    accessor = cluster.startServerVM(4, getProperties(), locatorPort);
+    client1 = cluster.startClientVM(5,
+        c -> c.withPoolSubscription(true).withLocatorConnection((locatorPort)));
+    client2 = cluster.startClientVM(6,
+        c -> c.withPoolSubscription(true).withLocatorConnection((locatorPort)));
+    dataStore1.invoke(this::initDataStore);
+    dataStore2.invoke(this::initDataStore);
+    dataStore3.invoke(this::initDataStore);
+    accessor.invoke(this::initAccessor);
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+  }
+
+  protected RegionShortcut getRegionShortCut() {
+    return RegionShortcut.PARTITION_REDUNDANT;
+  }
+
+  protected Properties getProperties() {
+    Properties properties = new Properties();
+    properties.setProperty("log-level", "info");
+    return properties;
+  }
+
+  private Region getRegion(boolean isClient) {
+    if (isClient) {
+      return getClientCache().getRegion(REGION_NAME);
+    } else {
+      return getCache().getRegion(REGION_NAME);
+    }
+  }
+
+  private void verifyRegionSize(boolean isClient, int expectedNum) {
+    assertThat(getRegion(isClient).size()).isEqualTo(expectedNum);
+  }
+
+  private void initClientCache() {
+    Region region = getClientCache().createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY)
+        .create(REGION_NAME);
+    region.registerInterestForAllKeys(InterestResultPolicy.KEYS);
+  }
+
+  private void initDataStore() {
+    getCache().createRegionFactory(getRegionShortCut())
+        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create())
+        .addCacheListener(new CountingCacheListener())
+        .create(REGION_NAME);
+  }
+
+  private void initAccessor() {
+    RegionShortcut shortcut = getRegionShortCut();
+    if (shortcut.isPersistent()) {
+      if (shortcut == RegionShortcut.PARTITION_PERSISTENT) {
+        shortcut = RegionShortcut.PARTITION;
+      } else if (shortcut == RegionShortcut.PARTITION_PERSISTENT_OVERFLOW) {
+        shortcut = RegionShortcut.PARTITION_OVERFLOW;
+      } else if (shortcut == RegionShortcut.PARTITION_REDUNDANT_PERSISTENT) {
+        shortcut = RegionShortcut.PARTITION_REDUNDANT;
+      } else if (shortcut == RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW) {
+        shortcut = RegionShortcut.PARTITION_REDUNDANT_OVERFLOW;
+      } else {
+        fail("Wrong region type:" + shortcut);
+      }
+    }
+    getCache().createRegionFactory(shortcut)
+        .setPartitionAttributes(
+            new PartitionAttributesFactory().setTotalNumBuckets(10).setLocalMaxMemory(0).create())
+        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create())
+        .addCacheListener(new CountingCacheListener())
+        .create(REGION_NAME);
+  }
+
+  private void feed(boolean isClient) {
+    Region region = getRegion(isClient);
+    IntStream.range(0, NUM_ENTRIES).forEach(i -> region.put(i, "value" + i));
+  }
+
+  private void verifyServerRegionSize(int expectedNum) {
+    accessor.invoke(() -> verifyRegionSize(false, expectedNum));
+    dataStore1.invoke(() -> verifyRegionSize(false, expectedNum));
+    dataStore2.invoke(() -> verifyRegionSize(false, expectedNum));
+    dataStore3.invoke(() -> verifyRegionSize(false, expectedNum));
+  }
+
+  private void verifyClientRegionSize(int expectedNum) {
+    client1.invoke(() -> verifyRegionSize(true, expectedNum));
+    // TODO: notify register clients
+    // client2.invoke(()->verifyRegionSize(true, expectedNum));
+  }
+
+  private void verifyCacheListenerTriggerCount(MemberVM serverVM) {
+    SerializableCallableIF<Integer> getListenerTriggerCount = () -> {
+      CountingCacheListener countingCacheListener =
+          (CountingCacheListener) getRegion(false).getAttributes()
+              .getCacheListeners()[0];
+      return countingCacheListener.getClears();
+    };
+
+    int count = accessor.invoke(getListenerTriggerCount)
+        + dataStore1.invoke(getListenerTriggerCount)
+        + dataStore2.invoke(getListenerTriggerCount)
+        + dataStore3.invoke(getListenerTriggerCount);
+    assertThat(count).isEqualTo(1);
+
+    if (serverVM != null) {
+      assertThat(serverVM.invoke(getListenerTriggerCount)).isEqualTo(1);
+    }
+  }
+
+  @Test
+  public void normalClearFromDataStore() {
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+    dataStore1.invoke(() -> getRegion(false).clear());
+    verifyServerRegionSize(0);
+    verifyCacheListenerTriggerCount(dataStore1);
+  }
+
+  @Test
+  public void normalClearFromAccessor() {
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+    accessor.invoke(() -> getRegion(false).clear());
+    verifyServerRegionSize(0);
+    verifyCacheListenerTriggerCount(accessor);
+  }
+
+  @Test
+  public void normalClearFromClient() {
+    client1.invoke(() -> feed(true));
+    verifyClientRegionSize(NUM_ENTRIES);
+    verifyServerRegionSize(NUM_ENTRIES);
+
+    client1.invoke(() -> getRegion(true).clear());
+    verifyServerRegionSize(0);
+    verifyClientRegionSize(0);
+    verifyCacheListenerTriggerCount(null);
+  }
+
+  private static class CountingCacheListener extends CacheListenerAdapter {
+    private final AtomicInteger clears = new AtomicInteger();
+
+    @Override
+    public void afterRegionClear(RegionEvent event) {
+      Region region = event.getRegion();
+      logger.info("Region " + region.getFullPath() + " is cleared.");
+      clears.incrementAndGet();
+    }
+
+    int getClears() {
+      return clears.get();
+    }
+  }
+}
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java
new file mode 100644
index 0000000..847699b
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.apache.geode.cache.RegionShortcut;
+
+public class PartitionedRegionPersistentClearDUnitTest extends PartitionedRegionClearDUnitTest {
+
+  protected RegionShortcut getRegionShortCut() {
+    return RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW;
+  }
+}
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionSingleNodeOperationsJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionSingleNodeOperationsJUnitTest.java
index b37945b..4f36060 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionSingleNodeOperationsJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionSingleNodeOperationsJUnitTest.java
@@ -25,7 +25,6 @@ import static org.junit.Assert.fail;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Set;
@@ -1298,71 +1297,6 @@ public class PartitionedRegionSingleNodeOperationsJUnitTest {
     }
   }
 
-  @Test
-  public void test023UnsupportedOps() throws Exception {
-    Region pr = null;
-    try {
-      pr = PartitionedRegionTestHelper.createPartitionedRegion("testUnsupportedOps",
-          String.valueOf(200), 0);
-
-      pr.put(new Integer(1), "one");
-      pr.put(new Integer(2), "two");
-      pr.put(new Integer(3), "three");
-      pr.getEntry("key");
-
-      try {
-        pr.clear();
-        fail(
-            "PartitionedRegionSingleNodeOperationTest:testUnSupportedOps() operation failed on a blank PartitionedRegion");
-      } catch (UnsupportedOperationException expected) {
-      }
-
-      // try {
-      // pr.entries(true);
-      // fail();
-      // }
-      // catch (UnsupportedOperationException expected) {
-      // }
-
-      // try {
-      // pr.entrySet(true);
-      // fail();
-      // }
-      // catch (UnsupportedOperationException expected) {
-      // }
-
-      try {
-        HashMap data = new HashMap();
-        data.put("foo", "bar");
-        data.put("bing", "bam");
-        data.put("supper", "hero");
-        pr.putAll(data);
-        // fail("testPutAll() does NOT throw UnsupportedOperationException");
-      } catch (UnsupportedOperationException onse) {
-      }
-
-
-      // try {
-      // pr.values();
-      // fail("testValues() does NOT throw UnsupportedOperationException");
-      // }
-      // catch (UnsupportedOperationException expected) {
-      // }
-
-
-      try {
-        pr.containsValue("foo");
-      } catch (UnsupportedOperationException ex) {
-        fail("PartitionedRegionSingleNodeOperationTest:testContainsValue() operation failed");
-      }
-
-    } finally {
-      if (pr != null) {
-        pr.destroyRegion();
-      }
-    }
-  }
-
   /**
    * This method validates size operations. It verifies that it returns correct size of the
    * PartitionedRegion.
diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 25c169b..88a8251 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1448,8 +1448,8 @@ fromData,27
 toData,27
 
 org/apache/geode/internal/cache/partitioned/ClearPRMessage,2
-fromData,30
-toData,44
+fromData,19
+toData,36
 
 org/apache/geode/internal/cache/partitioned/ClearPRMessage$ClearReplyMessage,2
 fromData,17
diff --git a/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java b/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java
index 7990323..c97f391 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java
@@ -288,6 +288,7 @@ import org.apache.geode.internal.cache.partitioned.BucketCountLoadProbe;
 import org.apache.geode.internal.cache.partitioned.BucketProfileUpdateMessage;
 import org.apache.geode.internal.cache.partitioned.BucketSizeMessage;
 import org.apache.geode.internal.cache.partitioned.BucketSizeMessage.BucketSizeReplyMessage;
+import org.apache.geode.internal.cache.partitioned.ClearPRMessage;
 import org.apache.geode.internal.cache.partitioned.ContainsKeyValueMessage;
 import org.apache.geode.internal.cache.partitioned.ContainsKeyValueMessage.ContainsKeyValueReplyMessage;
 import org.apache.geode.internal.cache.partitioned.CreateBucketMessage;
@@ -978,6 +979,8 @@ public class DSFIDFactory implements DataSerializableFixedID {
     serializer.registerDSFID(GATEWAY_SENDER_QUEUE_ENTRY_SYNCHRONIZATION_ENTRY,
         GatewaySenderQueueEntrySynchronizationOperation.GatewaySenderQueueEntrySynchronizationEntry.class);
     serializer.registerDSFID(ABORT_BACKUP_REQUEST, AbortBackupRequest.class);
+    serializer.registerDSFID(PR_CLEAR_MESSAGE, ClearPRMessage.class);
+    serializer.registerDSFID(PR_CLEAR_REPLY_MESSAGE, ClearPRMessage.ClearReplyMessage.class);
     serializer.registerDSFID(HOST_AND_PORT, HostAndPort.class);
     serializer.registerDSFID(DISTRIBUTED_PING_MESSAGE, DistributedPingMessage.class);
   }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
index 489d85a..84b5a3b 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
@@ -192,10 +192,6 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
   @MutableForTesting
   public static boolean ignoreReconnect = false;
 
-  /**
-   * Lock to prevent multiple threads on this member from performing a clear at the same time.
-   */
-  private final Object clearLock = new Object();
   private final ReentrantReadWriteLock failedInitialImageLock = new ReentrantReadWriteLock(true);
 
   @MakeNotStatic
@@ -933,11 +929,6 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
     }
   }
 
-  private void lockCheckReadiness() {
-    cache.getCancelCriterion().checkCancelInProgress(null);
-    checkReadiness();
-  }
-
   @Override
   Object validatedDestroy(Object key, EntryEventImpl event)
       throws TimeoutException, EntryNotFoundException, CacheWriterException {
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
index 73a67bf..a27e058 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
@@ -471,6 +471,11 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
   private final Lock clientMetaDataLock = new ReentrantLock();
 
   /**
+   * Lock to prevent multiple threads on this member from performing a clear at the same time.
+   */
+  protected final Object clearLock = new Object();
+
+  /**
    * Lock for updating the cache service profile for the region.
    */
   private final Lock cacheServiceProfileUpdateLock = new ReentrantLock();
@@ -2748,6 +2753,11 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
     checkRegionDestroyed(true);
   }
 
+  protected void lockCheckReadiness() {
+    cache.getCancelCriterion().checkCancelInProgress(null);
+    checkReadiness();
+  }
+
   /**
    * This method should be called when the caller cannot locate an entry and that condition is
    * unexpected. This will first double check the cache and region state before throwing an
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
index 78083cf..9ade05f 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
@@ -181,6 +181,7 @@ import org.apache.geode.internal.cache.execute.PartitionedRegionFunctionResultWa
 import org.apache.geode.internal.cache.execute.RegionFunctionContextImpl;
 import org.apache.geode.internal.cache.execute.ServerToClientFunctionResultSender;
 import org.apache.geode.internal.cache.ha.ThreadIdentifier;
+import org.apache.geode.internal.cache.partitioned.ClearPRMessage;
 import org.apache.geode.internal.cache.partitioned.ContainsKeyValueMessage;
 import org.apache.geode.internal.cache.partitioned.ContainsKeyValueMessage.ContainsKeyValueResponse;
 import org.apache.geode.internal.cache.partitioned.DestroyMessage;
@@ -2171,18 +2172,202 @@ public class PartitionedRegion extends LocalRegion
     throw new UnsupportedOperationException();
   }
 
-  /**
-   * @since GemFire 5.0
-   * @throws UnsupportedOperationException OVERRIDES
-   */
   @Override
-  public void clear() {
-    throw new UnsupportedOperationException();
+  void basicClear(RegionEventImpl regionEvent, boolean cacheWrite) {
+    final boolean isDebugEnabled = logger.isDebugEnabled();
+    synchronized (clearLock) {
+      final DistributedLockService lockService = getPartitionedRegionLockService();
+      try {
+        lockService.lock("_clearOperation" + this.getFullPath().replace('/', '_'), -1, -1);
+      } catch (IllegalStateException e) {
+        lockCheckReadiness();
+        throw e;
+      }
+      try {
+        if (cache.isCacheAtShutdownAll()) {
+          throw cache.getCacheClosedException("Cache is shutting down");
+        }
+
+        // create ClearPRMessage per bucket
+        List<ClearPRMessage> clearMsgList = createClearPRMessages();
+        for (ClearPRMessage clearPRMessage : clearMsgList) {
+          int bucketId = clearPRMessage.getBucketId();
+          checkReadiness();
+          long sendMessagesStartTime = 0;
+          if (isDebugEnabled) {
+            sendMessagesStartTime = System.currentTimeMillis();
+          }
+          try {
+            sendClearMsgByBucket(bucketId, clearPRMessage);
+          } catch (PartitionOfflineException poe) {
+            // TODO add a PartialResultException
+            logger.info("PR.sendClearMsgByBucket encountered PartitionOfflineException at bucket "
+                + bucketId, poe);
+          } catch (Exception e) {
+            logger.info("PR.sendClearMsgByBucket encountered exception at bucket " + bucketId, e);
+          }
+
+          if (isDebugEnabled) {
+            long now = System.currentTimeMillis();
+            logger.debug("PR.sendClearMsgByBucket for bucket {} took {} ms", bucketId,
+                (now - sendMessagesStartTime));
+          }
+          // TODO add psStats
+        }
+      } finally {
+        try {
+          lockService.unlock("_clearOperation" + this.getFullPath().replace('/', '_'));
+        } catch (IllegalStateException e) {
+          lockCheckReadiness();
+        }
+      }
+
+      // notify bridge clients at PR level
+      regionEvent.setEventType(EnumListenerEvent.AFTER_REGION_CLEAR);
+      boolean hasListener = hasListener();
+      if (hasListener) {
+        dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_CLEAR, regionEvent);
+      }
+      notifyBridgeClients(regionEvent);
+      logger.info("Partitioned region {} finsihed clear operation.", this.getFullPath());
+    }
   }
 
-  @Override
-  void basicClear(RegionEventImpl regionEvent, boolean cacheWrite) {
-    throw new UnsupportedOperationException();
+  void sendClearMsgByBucket(final Integer bucketId, ClearPRMessage clearPRMessage) {
+    RetryTimeKeeper retryTime = null;
+    InternalDistributedMember currentTarget = getNodeForBucketWrite(bucketId, null);
+    if (logger.isDebugEnabled()) {
+      logger.debug("PR.sendClearMsgByBucket:bucket {}'s currentTarget is {}", bucketId,
+          currentTarget);
+    }
+
+    long timeOut = 0;
+    int count = 0;
+    while (true) {
+      switch (count) {
+        case 0:
+          // Note we don't check for DM cancellation in common case.
+          // First time. Assume success, keep going.
+          break;
+        case 1:
+          this.cache.getCancelCriterion().checkCancelInProgress(null);
+          // Second time (first failure). Calculate timeout and keep going.
+          timeOut = System.currentTimeMillis() + this.retryTimeout;
+          break;
+        default:
+          this.cache.getCancelCriterion().checkCancelInProgress(null);
+          // test for timeout
+          long timeLeft = timeOut - System.currentTimeMillis();
+          if (timeLeft < 0) {
+            PRHARedundancyProvider.timedOut(this, null, null, "clear a bucket" + bucketId,
+                this.retryTimeout);
+            // NOTREACHED
+          }
+
+          // Didn't time out. Sleep a bit and then continue
+          boolean interrupted = Thread.interrupted();
+          try {
+            Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
+          } catch (InterruptedException ignore) {
+            interrupted = true;
+          } finally {
+            if (interrupted) {
+              Thread.currentThread().interrupt();
+            }
+          }
+          break;
+      } // switch
+      count++;
+
+      if (currentTarget == null) { // pick target
+        checkReadiness();
+        if (retryTime == null) {
+          retryTime = new RetryTimeKeeper(this.retryTimeout);
+        }
+
+        currentTarget = waitForNodeOrCreateBucket(retryTime, null, bucketId, false);
+        if (currentTarget == null) {
+          // the bucket does not exist, no need to clear
+          logger.info("Bucket " + bucketId + " does not contain data, no need to clear");
+          return;
+        } else {
+          if (logger.isDebugEnabled()) {
+            logger.debug("PR.sendClearMsgByBucket: new currentTarget is {}", currentTarget);
+          }
+        }
+
+        // It's possible this is a GemFire thread e.g. ServerConnection
+        // which got to this point because of a distributed system shutdown or
+        // region closure which uses interrupt to break any sleep() or wait() calls
+        // e.g. waitForPrimary or waitForBucketRecovery in which case throw exception
+        checkShutdown();
+        continue;
+      } // pick target
+
+      boolean result = false;
+      try {
+        final boolean isLocal = (this.localMaxMemory > 0) && currentTarget.equals(getMyId());
+        if (isLocal) {
+          result = clearPRMessage.doLocalClear(this);
+        } else {
+          ClearPRMessage.ClearResponse response = clearPRMessage.send(currentTarget, this);
+          if (response != null) {
+            this.prStats.incPartitionMessagesSent();
+            result = response.waitForResult();
+          }
+        }
+        if (result) {
+          return;
+        }
+      } catch (ForceReattemptException fre) {
+        checkReadiness();
+        InternalDistributedMember lastTarget = currentTarget;
+        if (retryTime == null) {
+          retryTime = new RetryTimeKeeper(this.retryTimeout);
+        }
+        currentTarget = getNodeForBucketWrite(bucketId, retryTime);
+        if (lastTarget.equals(currentTarget)) {
+          if (logger.isDebugEnabled()) {
+            logger.debug("PR.sendClearMsgByBucket: Retrying at the same node:{} due to {}",
+                currentTarget, fre.getMessage());
+          }
+          if (retryTime.overMaximum()) {
+            PRHARedundancyProvider.timedOut(this, null, null, "clear a bucket",
+                this.retryTimeout);
+            // NOTREACHED
+          }
+          retryTime.waitToRetryNode();
+        } else {
+          if (logger.isDebugEnabled()) {
+            logger.debug("PR.sendClearMsgByBucket: Old target was {}, Retrying {}", lastTarget,
+                currentTarget);
+          }
+        }
+      }
+
+      // It's possible this is a GemFire thread e.g. ServerConnection
+      // which got to this point because of a distributed system shutdown or
+      // region closure which uses interrupt to break any sleep() or wait()
+      // calls
+      // e.g. waitForPrimary or waitForBucketRecovery in which case throw
+      // exception
+      checkShutdown();
+
+      // If we get here, the attempt failed...
+      if (count == 1) {
+        // TODO prStats add ClearPRMsg retried
+        this.prStats.incPutAllMsgsRetried();
+      }
+    }
+  }
+
+  List<ClearPRMessage> createClearPRMessages() {
+    ArrayList<ClearPRMessage> clearMsgList = new ArrayList<>();
+    for (int bucketId = 0; bucketId < this.totalNumberOfBuckets; bucketId++) {
+      ClearPRMessage clearPRMessage = new ClearPRMessage(bucketId);
+      clearMsgList.add(clearPRMessage);
+    }
+    return clearMsgList;
   }
 
   @Override
@@ -2601,7 +2786,7 @@ public class PartitionedRegion extends LocalRegion
             retryTime = new RetryTimeKeeper(this.retryTimeout);
           }
 
-          currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId);
+          currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId, true);
           if (isDebugEnabled) {
             logger.debug("PR.sendMsgByBucket: event size is {}, new currentTarget is {}",
                 getEntrySize(event), currentTarget);
@@ -2742,7 +2927,7 @@ public class PartitionedRegion extends LocalRegion
             retryTime = new RetryTimeKeeper(this.retryTimeout);
           }
 
-          currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId);
+          currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId, true);
           if (logger.isDebugEnabled()) {
             logger.debug("PR.sendMsgByBucket: event size is {}, new currentTarget is {}",
                 getEntrySize(event), currentTarget);
@@ -2987,7 +3172,7 @@ public class PartitionedRegion extends LocalRegion
         if (retryTime == null) {
           retryTime = new RetryTimeKeeper(this.retryTimeout);
         }
-        currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId);
+        currentTarget = waitForNodeOrCreateBucket(retryTime, event, bucketId, true);
 
         // It's possible this is a GemFire thread e.g. ServerConnection
         // which got to this point because of a distributed system shutdown or
@@ -3146,10 +3331,11 @@ public class PartitionedRegion extends LocalRegion
    * @param retryTime the RetryTimeKeeper to track retry times
    * @param event the event used to get the entry size in the event a new bucket should be created
    * @param bucketId the identity of the bucket should it be created
+   * @param createIfNotExist boolean to indicate if to create a bucket if found not exist
    * @return a Node which contains the bucket, potentially null
    */
   private InternalDistributedMember waitForNodeOrCreateBucket(RetryTimeKeeper retryTime,
-      EntryEventImpl event, Integer bucketId) {
+      EntryEventImpl event, Integer bucketId, boolean createIfNotExist) {
     InternalDistributedMember newNode;
     if (retryTime.overMaximum()) {
       PRHARedundancyProvider.timedOut(this, null, null, "allocate a bucket",
@@ -3159,7 +3345,7 @@ public class PartitionedRegion extends LocalRegion
 
     retryTime.waitForBucketsRecovery();
     newNode = getNodeForBucketWrite(bucketId, retryTime);
-    if (newNode == null) {
+    if (newNode == null && createIfNotExist) {
       newNode = createBucket(bucketId, getEntrySize(event), retryTime);
     }
 
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEventImpl.java b/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEventImpl.java
index 402b7f2..f155a7e 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEventImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/RegionEventImpl.java
@@ -119,6 +119,11 @@ public class RegionEventImpl
     return region;
   }
 
+  public void setRegion(LocalRegion region) {
+    this.region = region;
+    this.distributedMember = region.getMyId();
+  }
+
   @Override
   public Operation getOperation() {
     return this.op;
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
index 1a8aba1..9fa8057 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
@@ -26,7 +26,8 @@ import org.apache.logging.log4j.Logger;
 import org.apache.geode.DataSerializer;
 import org.apache.geode.annotations.VisibleForTesting;
 import org.apache.geode.cache.CacheException;
-import org.apache.geode.distributed.DistributedLockService;
+import org.apache.geode.cache.Operation;
+import org.apache.geode.cache.persistence.PartitionOfflineException;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.internal.ClusterDistributionManager;
 import org.apache.geode.distributed.internal.DirectReplyProcessor;
@@ -44,7 +45,6 @@ import org.apache.geode.internal.cache.BucketRegion;
 import org.apache.geode.internal.cache.EventID;
 import org.apache.geode.internal.cache.ForceReattemptException;
 import org.apache.geode.internal.cache.PartitionedRegion;
-import org.apache.geode.internal.cache.PartitionedRegionHelper;
 import org.apache.geode.internal.cache.RegionEventImpl;
 import org.apache.geode.internal.logging.log4j.LogMarker;
 import org.apache.geode.internal.serialization.DeserializationContext;
@@ -54,16 +54,10 @@ import org.apache.geode.logging.internal.log4j.api.LogService;
 public class ClearPRMessage extends PartitionMessageWithDirectReply {
   private static final Logger logger = LogService.getLogger();
 
-  private RegionEventImpl regionEvent;
-
   private Integer bucketId;
 
-  /** The time in ms to wait for a lock to be obtained during doLocalClear() */
-  public static final int LOCK_WAIT_TIMEOUT_MS = 1000;
   public static final String BUCKET_NON_PRIMARY_MESSAGE =
       "The bucket region on target member is no longer primary";
-  public static final String BUCKET_REGION_LOCK_UNAVAILABLE_MESSAGE =
-      "A lock for the bucket region could not be obtained.";
   public static final String EXCEPTION_THROWN_DURING_CLEAR_OPERATION =
       "An exception was thrown during the local clear operation: ";
 
@@ -79,14 +73,6 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
 
   public ClearPRMessage(int bucketId) {
     this.bucketId = bucketId;
-
-    // These are both used by the parent class, but don't apply to this message type
-    this.notificationOnly = false;
-    this.posDup = false;
-  }
-
-  public void setRegionEvent(RegionEventImpl event) {
-    regionEvent = event;
   }
 
   public void initMessage(PartitionedRegion region, Set<InternalDistributedMember> recipients,
@@ -103,16 +89,6 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     }
   }
 
-  @Override
-  public boolean isSevereAlertCompatible() {
-    // allow forced-disconnect processing for all cache op messages
-    return true;
-  }
-
-  public RegionEventImpl getRegionEvent() {
-    return regionEvent;
-  }
-
   public ClearResponse send(DistributedMember recipient, PartitionedRegion region)
       throws ForceReattemptException {
     Set<InternalDistributedMember> recipients =
@@ -125,7 +101,7 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
 
     Set<InternalDistributedMember> failures = region.getDistributionManager().putOutgoing(this);
     if (failures != null && failures.size() > 0) {
-      throw new ForceReattemptException("Failed sending <" + this + ">");
+      throw new ForceReattemptException("Failed sending <" + this + "> due to " + failures);
     }
     return clearResponse;
   }
@@ -143,7 +119,6 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     } else {
       InternalDataSerializer.writeSignedVL(bucketId, out);
     }
-    DataSerializer.writeObject(regionEvent, out);
   }
 
   @Override
@@ -151,12 +126,11 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
       throws IOException, ClassNotFoundException {
     super.fromData(in, context);
     this.bucketId = (int) InternalDataSerializer.readSignedVL(in);
-    this.regionEvent = DataSerializer.readObject(in);
   }
 
   @Override
   public EventID getEventID() {
-    return regionEvent.getEventId();
+    return null;
   }
 
   /**
@@ -169,60 +143,51 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
   protected boolean operateOnPartitionedRegion(ClusterDistributionManager distributionManager,
       PartitionedRegion region, long startTime) {
     try {
-      result = doLocalClear(region);
+      this.result = doLocalClear(region);
     } catch (ForceReattemptException ex) {
       sendReply(getSender(), getProcessorId(), distributionManager, new ReplyException(ex), region,
           startTime);
       return false;
     }
-    sendReply(getSender(), getProcessorId(), distributionManager, null, region, startTime);
-    return false;
+    return this.result;
   }
 
-  public boolean doLocalClear(PartitionedRegion region) throws ForceReattemptException {
+  public Integer getBucketId() {
+    return this.bucketId;
+  }
+
+  public boolean doLocalClear(PartitionedRegion region)
+      throws ForceReattemptException {
     // Retrieve local bucket region which matches target bucketId
-    BucketRegion bucketRegion = region.getDataStore().getInitializedBucketForId(null, bucketId);
+    BucketRegion bucketRegion =
+        region.getDataStore().getInitializedBucketForId(null, this.bucketId);
 
-    // Check if we are primary, throw exception if not
-    if (!bucketRegion.isPrimary()) {
+    boolean lockedForPrimary = bucketRegion.doLockForPrimary(false);
+    // Check if we obtained primary lock, throw exception if not
+    if (!lockedForPrimary) {
       throw new ForceReattemptException(BUCKET_NON_PRIMARY_MESSAGE);
     }
-
-    DistributedLockService lockService = getPartitionRegionLockService();
-    String lockName = bucketRegion.getFullPath();
     try {
-      boolean locked = lockService.lock(lockName, LOCK_WAIT_TIMEOUT_MS, -1);
-
-      if (!locked) {
-        throw new ForceReattemptException(BUCKET_REGION_LOCK_UNAVAILABLE_MESSAGE);
-      }
-
-      // Double check if we are still primary, as this could have changed between our first check
-      // and obtaining the lock
-      if (!bucketRegion.isPrimary()) {
-        throw new ForceReattemptException(BUCKET_NON_PRIMARY_MESSAGE);
-      }
-
-      try {
-        bucketRegion.cmnClearRegion(regionEvent, true, true);
-      } catch (Exception ex) {
-        throw new ForceReattemptException(
-            EXCEPTION_THROWN_DURING_CLEAR_OPERATION + ex.getClass().getName(), ex);
-      }
-
+      RegionEventImpl regionEvent = new RegionEventImpl();
+      regionEvent.setOperation(Operation.REGION_CLEAR);
+      regionEvent.setRegion(bucketRegion);
+      bucketRegion.cmnClearRegion(regionEvent, true, true);
+    } catch (PartitionOfflineException poe) {
+      logger.info(
+          "All members holding data for bucket {} are offline, no more retries will be attempted",
+          this.bucketId,
+          poe);
+      throw poe;
+    } catch (Exception ex) {
+      throw new ForceReattemptException(
+          EXCEPTION_THROWN_DURING_CLEAR_OPERATION + ex.getClass().getName(), ex);
     } finally {
-      lockService.unlock(lockName);
+      bucketRegion.doUnlockForPrimary();
     }
 
     return true;
   }
 
-  // Extracted for testing
-  protected DistributedLockService getPartitionRegionLockService() {
-    return DistributedLockService
-        .getServiceNamed(PartitionedRegionHelper.PARTITION_LOCK_SERVICE_NAME);
-  }
-
   @Override
   public boolean canStartRemoteTransaction() {
     return false;
@@ -247,39 +212,7 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     buff.append("; bucketId=").append(this.bucketId);
   }
 
-  @Override
-  public String toString() {
-    StringBuilder buff = new StringBuilder();
-    String className = getClass().getName();
-    buff.append(className.substring(className.indexOf(PN_TOKEN) + PN_TOKEN.length())); // partition.<foo>
-    buff.append("(prid="); // make sure this is the first one
-    buff.append(this.regionId);
-
-    // Append name, if we have it
-    String name = null;
-    try {
-      PartitionedRegion region = PartitionedRegion.getPRFromId(this.regionId);
-      if (region != null) {
-        name = region.getFullPath();
-      }
-    } catch (Exception ignore) {
-      /* ignored */
-    }
-    if (name != null) {
-      buff.append(" (name = \"").append(name).append("\")");
-    }
-
-    appendFields(buff);
-    buff.append(" ,distTx=");
-    buff.append(this.isTransactionDistributed);
-    buff.append(")");
-    return buff.toString();
-  }
-
   public static class ClearReplyMessage extends ReplyMessage {
-    /** Result of the Clear operation */
-    boolean result;
-
     @Override
     public boolean getInlineProcess() {
       return true;
@@ -293,16 +226,21 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
 
     private ClearReplyMessage(int processorId, boolean result, ReplyException ex) {
       super();
-      this.result = result;
       setProcessorId(processorId);
-      setException(ex);
+      if (ex != null) {
+        setException(ex);
+      } else {
+        setReturnValue(result);
+      }
     }
 
-    /** Send an ack */
+    /**
+     * Send an ack
+     */
     public static void send(InternalDistributedMember recipient, int processorId,
         ReplySender replySender,
         boolean result, ReplyException ex) {
-      Assert.assertTrue(recipient != null, "ClearReplyMessage NULL reply message");
+      Assert.assertNotNull(recipient, "ClearReplyMessage recipient was NULL.");
       ClearReplyMessage message = new ClearReplyMessage(processorId, result, ex);
       message.setRecipient(recipient);
       replySender.putOutgoing(message);
@@ -340,23 +278,11 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     }
 
     @Override
-    public void fromData(DataInput in,
-        DeserializationContext context) throws IOException, ClassNotFoundException {
-      super.fromData(in, context);
-      this.result = in.readBoolean();
-    }
-
-    @Override
-    public void toData(DataOutput out,
-        SerializationContext context) throws IOException {
-      super.toData(out, context);
-      out.writeBoolean(this.result);
-    }
-
-    @Override
     public String toString() {
-      return "ClearReplyMessage " + "processorid=" + this.processorId + " returning " + this.result
-          + " exception=" + getException();
+      StringBuilder stringBuilder = new StringBuilder(super.toString());
+      stringBuilder.append(" returnValue=");
+      stringBuilder.append(getReturnValue());
+      return stringBuilder.toString();
     }
   }
 
@@ -372,7 +298,9 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     }
 
     public void setResponse(ClearReplyMessage response) {
-      this.returnValue = response.result;
+      if (response.getException() == null) {
+        this.returnValue = (boolean) response.getReturnValue();
+      }
     }
 
     /**
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java
index 2cf5231..acdd4fc 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java
@@ -20,7 +20,6 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.notNull;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doNothing;
@@ -38,7 +37,6 @@ import java.util.Set;
 import org.junit.Before;
 import org.junit.Test;
 
-import org.apache.geode.distributed.DistributedLockService;
 import org.apache.geode.distributed.internal.ClusterDistributionManager;
 import org.apache.geode.distributed.internal.DMStats;
 import org.apache.geode.distributed.internal.DistributionManager;
@@ -50,6 +48,7 @@ import org.apache.geode.internal.cache.ForceReattemptException;
 import org.apache.geode.internal.cache.PartitionedRegion;
 import org.apache.geode.internal.cache.PartitionedRegionDataStore;
 import org.apache.geode.internal.cache.PartitionedRegionStats;
+import org.apache.geode.internal.cache.RegionEventImpl;
 
 public class ClearPRMessageTest {
 
@@ -61,11 +60,14 @@ public class ClearPRMessageTest {
   @Before
   public void setup() throws ForceReattemptException {
     message = spy(new ClearPRMessage());
+    InternalDistributedMember member = mock(InternalDistributedMember.class);
     region = mock(PartitionedRegion.class, RETURNS_DEEP_STUBS);
     dataStore = mock(PartitionedRegionDataStore.class);
     when(region.getDataStore()).thenReturn(dataStore);
+    when(region.getFullPath()).thenReturn("/test");
     bucketRegion = mock(BucketRegion.class);
     when(dataStore.getInitializedBucketForId(any(), any())).thenReturn(bucketRegion);
+    RegionEventImpl bucketRegionEventImpl = mock(RegionEventImpl.class);
   }
 
   @Test
@@ -79,44 +81,19 @@ public class ClearPRMessageTest {
 
   @Test
   public void doLocalClearThrowsExceptionWhenLockCannotBeObtained() {
-    DistributedLockService mockLockService = mock(DistributedLockService.class);
-    doReturn(mockLockService).when(message).getPartitionRegionLockService();
-
-    when(mockLockService.lock(anyString(), anyLong(), anyLong())).thenReturn(false);
-    when(bucketRegion.isPrimary()).thenReturn(true);
-
-    assertThatThrownBy(() -> message.doLocalClear(region))
-        .isInstanceOf(ForceReattemptException.class)
-        .hasMessageContaining(ClearPRMessage.BUCKET_REGION_LOCK_UNAVAILABLE_MESSAGE);
-  }
-
-  @Test
-  public void doLocalClearThrowsExceptionWhenBucketIsNotPrimaryAfterObtainingLock() {
-    DistributedLockService mockLockService = mock(DistributedLockService.class);
-    doReturn(mockLockService).when(message).getPartitionRegionLockService();
-
-    // Be primary on the first check, then be not primary on the second check
-    when(bucketRegion.isPrimary()).thenReturn(true).thenReturn(false);
-    when(mockLockService.lock(any(), anyLong(), anyLong())).thenReturn(true);
+    when(bucketRegion.doLockForPrimary(false)).thenReturn(false);
 
     assertThatThrownBy(() -> message.doLocalClear(region))
         .isInstanceOf(ForceReattemptException.class)
         .hasMessageContaining(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
-    // Confirm that we actually obtained and released the lock
-    verify(mockLockService, times(1)).lock(any(), anyLong(), anyLong());
-    verify(mockLockService, times(1)).unlock(any());
   }
 
   @Test
   public void doLocalClearThrowsForceReattemptExceptionWhenAnExceptionIsThrownDuringClearOperation() {
-    DistributedLockService mockLockService = mock(DistributedLockService.class);
-    doReturn(mockLockService).when(message).getPartitionRegionLockService();
     NullPointerException exception = new NullPointerException("Error encountered");
     doThrow(exception).when(bucketRegion).cmnClearRegion(any(), anyBoolean(), anyBoolean());
 
-    // Be primary on the first check, then be not primary on the second check
-    when(bucketRegion.isPrimary()).thenReturn(true);
-    when(mockLockService.lock(any(), anyLong(), anyLong())).thenReturn(true);
+    when(bucketRegion.doLockForPrimary(false)).thenReturn(true);
 
     assertThatThrownBy(() -> message.doLocalClear(region))
         .isInstanceOf(ForceReattemptException.class)
@@ -129,21 +106,13 @@ public class ClearPRMessageTest {
   @Test
   public void doLocalClearInvokesCmnClearRegionWhenBucketIsPrimaryAndLockIsObtained()
       throws ForceReattemptException {
-    DistributedLockService mockLockService = mock(DistributedLockService.class);
-    doReturn(mockLockService).when(message).getPartitionRegionLockService();
-
 
     // Be primary on the first check, then be not primary on the second check
-    when(bucketRegion.isPrimary()).thenReturn(true);
-    when(mockLockService.lock(any(), anyLong(), anyLong())).thenReturn(true);
+    when(bucketRegion.doLockForPrimary(false)).thenReturn(true);
     assertThat(message.doLocalClear(region)).isTrue();
 
     // Confirm that cmnClearRegion was called
     verify(bucketRegion, times(1)).cmnClearRegion(any(), anyBoolean(), anyBoolean());
-
-    // Confirm that we actually obtained and released the lock
-    verify(mockLockService, times(1)).lock(any(), anyLong(), anyLong());
-    verify(mockLockService, times(1)).unlock(any());
   }
 
   @Test
@@ -197,6 +166,7 @@ public class ClearPRMessageTest {
     int processorId = 1000;
     int startTime = 0;
 
+    doReturn(0).when(message).getBucketId();
     doReturn(true).when(message).doLocalClear(region);
     doReturn(sender).when(message).getSender();
     doReturn(processorId).when(message).getProcessorId();
@@ -206,8 +176,9 @@ public class ClearPRMessageTest {
     doNothing().when(message).sendReply(any(), anyInt(), any(), any(), any(), anyLong());
 
     message.operateOnPartitionedRegion(distributionManager, region, startTime);
+    assertThat(message.result).isTrue();
 
-    verify(message, times(1)).sendReply(sender, processorId, distributionManager, null, region,
+    verify(message, times(0)).sendReply(sender, processorId, distributionManager, null, region,
         startTime);
   }
 
@@ -222,6 +193,7 @@ public class ClearPRMessageTest {
     ForceReattemptException exception =
         new ForceReattemptException(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
 
+    doReturn(0).when(message).getBucketId();
     doThrow(exception).when(message).doLocalClear(region);
     doReturn(sender).when(message).getSender();
     doReturn(processorId).when(message).getProcessorId();


[geode] 03/11: PR.clear's event id should be created and used in BR (#4805)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit f868c0f99ed9ac0c95184fbdad59e4cd06fb558e
Author: Xiaojian Zhou <ge...@users.noreply.github.com>
AuthorDate: Mon Mar 16 17:35:35 2020 -0700

    PR.clear's event id should be created and used in BR (#4805)
    
    * GEODE-7857: PR.clear's event id should be created and used in BR
---
 .../PartitionedRegionPersistentClearDUnitTest.java |  2 +-
 .../codeAnalysis/sanctionedDataSerializables.txt   |  4 +-
 .../geode/internal/cache/PartitionedRegion.java    |  8 +--
 .../internal/cache/partitioned/ClearPRMessage.java | 12 ++--
 .../internal/cache/PartitionedRegionTest.java      | 65 ++++++++++++++++++++++
 5 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java
index 847699b..c758446 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionPersistentClearDUnitTest.java
@@ -21,6 +21,6 @@ import org.apache.geode.cache.RegionShortcut;
 public class PartitionedRegionPersistentClearDUnitTest extends PartitionedRegionClearDUnitTest {
 
   protected RegionShortcut getRegionShortCut() {
-    return RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW;
+    return RegionShortcut.PARTITION_REDUNDANT_PERSISTENT;
   }
 }
diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 88a8251..25c169b 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1448,8 +1448,8 @@ fromData,27
 toData,27
 
 org/apache/geode/internal/cache/partitioned/ClearPRMessage,2
-fromData,19
-toData,36
+fromData,30
+toData,44
 
 org/apache/geode/internal/cache/partitioned/ClearPRMessage$ClearReplyMessage,2
 fromData,17
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
index 9ade05f..7b5a2c7 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
@@ -2189,7 +2189,7 @@ public class PartitionedRegion extends LocalRegion
         }
 
         // create ClearPRMessage per bucket
-        List<ClearPRMessage> clearMsgList = createClearPRMessages();
+        List<ClearPRMessage> clearMsgList = createClearPRMessages(regionEvent.getEventId());
         for (ClearPRMessage clearPRMessage : clearMsgList) {
           int bucketId = clearPRMessage.getBucketId();
           checkReadiness();
@@ -2361,10 +2361,10 @@ public class PartitionedRegion extends LocalRegion
     }
   }
 
-  List<ClearPRMessage> createClearPRMessages() {
+  List<ClearPRMessage> createClearPRMessages(EventID eventID) {
     ArrayList<ClearPRMessage> clearMsgList = new ArrayList<>();
-    for (int bucketId = 0; bucketId < this.totalNumberOfBuckets; bucketId++) {
-      ClearPRMessage clearPRMessage = new ClearPRMessage(bucketId);
+    for (int bucketId = 0; bucketId < getTotalNumberOfBuckets(); bucketId++) {
+      ClearPRMessage clearPRMessage = new ClearPRMessage(bucketId, eventID);
       clearMsgList.add(clearPRMessage);
     }
     return clearMsgList;
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
index 9fa8057..cc01920 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
@@ -56,6 +56,8 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
 
   private Integer bucketId;
 
+  private EventID eventID;
+
   public static final String BUCKET_NON_PRIMARY_MESSAGE =
       "The bucket region on target member is no longer primary";
   public static final String EXCEPTION_THROWN_DURING_CLEAR_OPERATION =
@@ -71,8 +73,9 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
    */
   public ClearPRMessage() {}
 
-  public ClearPRMessage(int bucketId) {
+  public ClearPRMessage(int bucketId, EventID eventID) {
     this.bucketId = bucketId;
+    this.eventID = eventID;
   }
 
   public void initMessage(PartitionedRegion region, Set<InternalDistributedMember> recipients,
@@ -119,6 +122,7 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
     } else {
       InternalDataSerializer.writeSignedVL(bucketId, out);
     }
+    DataSerializer.writeObject(this.eventID, out);
   }
 
   @Override
@@ -126,6 +130,7 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
       throws IOException, ClassNotFoundException {
     super.fromData(in, context);
     this.bucketId = (int) InternalDataSerializer.readSignedVL(in);
+    this.eventID = (EventID) DataSerializer.readObject(in);
   }
 
   @Override
@@ -168,9 +173,8 @@ public class ClearPRMessage extends PartitionMessageWithDirectReply {
       throw new ForceReattemptException(BUCKET_NON_PRIMARY_MESSAGE);
     }
     try {
-      RegionEventImpl regionEvent = new RegionEventImpl();
-      regionEvent.setOperation(Operation.REGION_CLEAR);
-      regionEvent.setRegion(bucketRegion);
+      RegionEventImpl regionEvent = new RegionEventImpl(bucketRegion, Operation.REGION_CLEAR, null,
+          false, region.getMyId(), eventID);
       bucketRegion.cmnClearRegion(regionEvent, true, true);
     } catch (PartitionOfflineException poe) {
       logger.info(
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java
index 742db8a..898c4f7 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java
@@ -21,10 +21,12 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.catchThrowable;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
@@ -39,6 +41,7 @@ import static org.mockito.quality.Strictness.STRICT_STUBS;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -55,6 +58,7 @@ import org.mockito.junit.MockitoRule;
 import org.apache.geode.CancelCriterion;
 import org.apache.geode.Statistics;
 import org.apache.geode.cache.AttributesFactory;
+import org.apache.geode.cache.CacheClosedException;
 import org.apache.geode.cache.CacheLoader;
 import org.apache.geode.cache.CacheWriter;
 import org.apache.geode.cache.Operation;
@@ -71,6 +75,7 @@ import org.apache.geode.distributed.internal.DistributionManager;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
 import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
 import org.apache.geode.internal.cache.control.InternalResourceManager;
+import org.apache.geode.internal.cache.partitioned.ClearPRMessage;
 import org.apache.geode.internal.cache.partitioned.FetchKeysMessage;
 import org.apache.geode.internal.cache.partitioned.colocation.ColocationLoggerFactory;
 import org.apache.geode.internal.cache.tier.sockets.ServerConnection;
@@ -208,6 +213,66 @@ public class PartitionedRegionTest {
   }
 
   @Test
+  public void clearShouldNotThrowUnsupportedOperationException() {
+    PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
+    doNothing().when(spyPartitionedRegion).checkReadiness();
+    doCallRealMethod().when(spyPartitionedRegion).basicClear(any());
+    doNothing().when(spyPartitionedRegion).basicClear(any(), anyBoolean());
+    spyPartitionedRegion.clear();
+  }
+
+  @Test(expected = CacheClosedException.class)
+  public void clearShouldThrowCacheClosedExceptionIfShutdownAll() {
+    PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
+    RegionEventImpl regionEvent =
+        new RegionEventImpl(spyPartitionedRegion, Operation.REGION_CLEAR, null, false,
+            spyPartitionedRegion.getMyId(), true);
+    when(cache.isCacheAtShutdownAll()).thenReturn(true);
+    when(cache.getCacheClosedException("Cache is shutting down"))
+        .thenReturn(new CacheClosedException("Cache is shutting down"));
+    DistributedLockService lockService = mock(DistributedLockService.class);
+    when(spyPartitionedRegion.getPartitionedRegionLockService()).thenReturn(lockService);
+    String lockName = "_clearOperation" + spyPartitionedRegion.getFullPath().replace('/', '_');
+    when(lockService.lock(lockName, -1, -1)).thenReturn(true);
+    spyPartitionedRegion.basicClear(regionEvent, true);
+  }
+
+  @Test
+  public void createClearPRMessagesShouldCreateMessagePerBucket() {
+    PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
+    RegionEventImpl regionEvent =
+        new RegionEventImpl(spyPartitionedRegion, Operation.REGION_CLEAR, null, false,
+            spyPartitionedRegion.getMyId(), true);
+    when(spyPartitionedRegion.getTotalNumberOfBuckets()).thenReturn(3);
+    EventID eventID = new EventID(spyPartitionedRegion.getCache().getDistributedSystem());
+    List<ClearPRMessage> msgs = spyPartitionedRegion.createClearPRMessages(eventID);
+    assertThat(msgs.size()).isEqualTo(3);
+  }
+
+  @Test
+  public void sendEachMessagePerBucket() {
+    PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
+    RegionEventImpl regionEvent =
+        new RegionEventImpl(spyPartitionedRegion, Operation.REGION_CLEAR, null, false,
+            spyPartitionedRegion.getMyId(), true);
+    when(cache.isCacheAtShutdownAll()).thenReturn(false);
+    DistributedLockService lockService = mock(DistributedLockService.class);
+    when(spyPartitionedRegion.getPartitionedRegionLockService()).thenReturn(lockService);
+    when(spyPartitionedRegion.getTotalNumberOfBuckets()).thenReturn(3);
+    String lockName = "_clearOperation" + spyPartitionedRegion.getFullPath().replace('/', '_');
+    when(lockService.lock(lockName, -1, -1)).thenReturn(true);
+    when(spyPartitionedRegion.hasListener()).thenReturn(true);
+    doNothing().when(spyPartitionedRegion).dispatchListenerEvent(any(), any());
+    doNothing().when(spyPartitionedRegion).notifyBridgeClients(eq(regionEvent));
+    doNothing().when(spyPartitionedRegion).checkReadiness();
+    doNothing().when(lockService).unlock(lockName);
+    spyPartitionedRegion.basicClear(regionEvent, true);
+    verify(spyPartitionedRegion, times(3)).sendClearMsgByBucket(any(), any());
+    verify(spyPartitionedRegion, times(1)).dispatchListenerEvent(any(), any());
+    verify(spyPartitionedRegion, times(1)).notifyBridgeClients(eq(regionEvent));
+  }
+
+  @Test
   public void getBucketNodeForReadOrWriteReturnsPrimaryNodeForRegisterInterest() {
     // ARRANGE
     EntryEventImpl clientEvent = mock(EntryEventImpl.class);


[geode] 01/11: GEODE-7683: introduce BR.cmnClearRegion

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 22ca1ab16796addb1c32fe88b7e59f2a770b6033
Author: zhouxh <gz...@pivotal.io>
AuthorDate: Mon Jan 27 17:02:48 2020 -0800

    GEODE-7683: introduce BR.cmnClearRegion
    
    Co-authored-by: Xiaojian Zhou <gz...@pivotal.io>
    
    GEODE-7684: Create messaging class for PR Clear (#4689)
    
    * Added new message class and test
    
    Co-authored-by: Benjamin Ross <br...@pivotal.io>
    Co-authored-by: Donal Evans <do...@pivotal.io>
---
 .../codeAnalysis/sanctionedDataSerializables.txt   |   8 +
 .../apache/geode/internal/cache/BucketRegion.java  |  38 +-
 .../geode/internal/cache/DistributedRegion.java    |  23 +-
 .../internal/cache/partitioned/ClearPRMessage.java | 388 +++++++++++++++++++++
 .../internal/cache/BucketRegionJUnitTest.java      |  77 ++++
 .../internal/cache/DistributedRegionJUnitTest.java |  18 +
 .../cache/partitioned/ClearPRMessageTest.java      | 288 +++++++++++++++
 .../serialization/DataSerializableFixedID.java     |   3 +
 8 files changed, 832 insertions(+), 11 deletions(-)

diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 6c48fc4..25c169b 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1447,6 +1447,14 @@ org/apache/geode/internal/cache/partitioned/BucketSizeMessage$BucketSizeReplyMes
 fromData,27
 toData,27
 
+org/apache/geode/internal/cache/partitioned/ClearPRMessage,2
+fromData,30
+toData,44
+
+org/apache/geode/internal/cache/partitioned/ClearPRMessage$ClearReplyMessage,2
+fromData,17
+toData,17
+
 org/apache/geode/internal/cache/partitioned/ColocatedRegionDetails,2
 fromData,81
 toData,133
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
index d91786f..e4fa7ef 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
@@ -557,6 +557,36 @@ public class BucketRegion extends DistributedRegion implements Bucket {
     }
   }
 
+  @Override
+  public void cmnClearRegion(RegionEventImpl regionEvent, boolean cacheWrite, boolean useRVV) {
+    if (!getBucketAdvisor().isPrimary()) {
+      if (logger.isDebugEnabled()) {
+        logger.debug("Not primary bucket when doing clear, do nothing");
+      }
+      return;
+    }
+
+    boolean enableRVV = useRVV && getConcurrencyChecksEnabled();
+    RegionVersionVector rvv = null;
+    if (enableRVV) {
+      rvv = getVersionVector().getCloneForTransmission();
+    }
+
+    // get rvvLock
+    Set<InternalDistributedMember> participants =
+        getCacheDistributionAdvisor().adviseInvalidateRegion();
+    try {
+      obtainWriteLocksForClear(regionEvent, participants);
+      // no need to dominate my own rvv.
+      // Clear is on going here, there won't be GII for this member
+      clearRegionLocally(regionEvent, cacheWrite, null);
+      distributeClearOperation(regionEvent, rvv, participants);
+
+      // TODO: call reindexUserDataRegion if there're lucene indexes
+    } finally {
+      releaseWriteLocksForClear(regionEvent, participants);
+    }
+  }
 
   long generateTailKey() {
     long key = eventSeqNum.addAndGet(partitionedRegion.getTotalNumberOfBuckets());
@@ -2093,11 +2123,9 @@ public class BucketRegion extends DistributedRegion implements Bucket {
       // if GII has failed, because there is not primary. So it's safe to set these
       // counters to 0.
       oldMemValue = bytesInMemory.getAndSet(0);
-    }
-
-    else {
-      throw new InternalGemFireError(
-          "Trying to clear a bucket region that was not destroyed or in initialization.");
+    } else {
+      // BucketRegion's clear is supported now
+      oldMemValue = bytesInMemory.getAndSet(0);
     }
     if (oldMemValue != BUCKET_DESTROYED) {
       partitionedRegion.getPrStats().incDataStoreEntryCount(-sizeBeforeClear);
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
index b822dde..489d85a 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
@@ -2013,6 +2013,10 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
     super.basicClear(regionEvent, cacheWrite);
   }
 
+  void distributeClearOperation(RegionEventImpl regionEvent, RegionVersionVector rvv,
+      Set<InternalDistributedMember> participants) {
+    DistributedClearOperation.clear(regionEvent, rvv, participants);
+  }
 
   @Override
   void cmnClearRegion(RegionEventImpl regionEvent, boolean cacheWrite, boolean useRVV) {
@@ -2035,7 +2039,7 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
             obtainWriteLocksForClear(regionEvent, participants);
             clearRegionLocally(regionEvent, cacheWrite, null);
             if (!regionEvent.isOriginRemote() && regionEvent.getOperation().isDistributed()) {
-              DistributedClearOperation.clear(regionEvent, null, participants);
+              distributeClearOperation(regionEvent, null, participants);
             }
           } finally {
             releaseWriteLocksForClear(regionEvent, participants);
@@ -2091,10 +2095,12 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
   /**
    * obtain locks preventing generation of new versions in other members
    */
-  private void obtainWriteLocksForClear(RegionEventImpl regionEvent,
+  protected void obtainWriteLocksForClear(RegionEventImpl regionEvent,
       Set<InternalDistributedMember> participants) {
     lockLocallyForClear(getDistributionManager(), getMyId(), regionEvent);
-    DistributedClearOperation.lockAndFlushToOthers(regionEvent, participants);
+    if (!isUsedForPartitionedRegionBucket()) {
+      DistributedClearOperation.lockAndFlushToOthers(regionEvent, participants);
+    }
   }
 
   /**
@@ -2131,7 +2137,7 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
   /**
    * releases the locks obtained in obtainWriteLocksForClear
    */
-  private void releaseWriteLocksForClear(RegionEventImpl regionEvent,
+  protected void releaseWriteLocksForClear(RegionEventImpl regionEvent,
       Set<InternalDistributedMember> participants) {
 
     ARMLockTestHook armLockTestHook = getRegionMap().getARMLockTestHook();
@@ -2139,8 +2145,13 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
       armLockTestHook.beforeRelease(this, regionEvent);
     }
 
-    getVersionVector().unlockForClear(getMyId());
-    DistributedClearOperation.releaseLocks(regionEvent, participants);
+    RegionVersionVector rvv = getVersionVector();
+    if (rvv != null) {
+      rvv.unlockForClear(getMyId());
+    }
+    if (!isUsedForPartitionedRegionBucket()) {
+      DistributedClearOperation.releaseLocks(regionEvent, participants);
+    }
 
     if (armLockTestHook != null) {
       armLockTestHook.afterRelease(this, regionEvent);
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
new file mode 100644
index 0000000..1a8aba1
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/ClearPRMessage.java
@@ -0,0 +1,388 @@
+/*
+ * 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.partitioned;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.DataSerializer;
+import org.apache.geode.annotations.VisibleForTesting;
+import org.apache.geode.cache.CacheException;
+import org.apache.geode.distributed.DistributedLockService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.internal.ClusterDistributionManager;
+import org.apache.geode.distributed.internal.DirectReplyProcessor;
+import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.distributed.internal.ReplyException;
+import org.apache.geode.distributed.internal.ReplyMessage;
+import org.apache.geode.distributed.internal.ReplyProcessor21;
+import org.apache.geode.distributed.internal.ReplySender;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.Assert;
+import org.apache.geode.internal.InternalDataSerializer;
+import org.apache.geode.internal.NanoTimer;
+import org.apache.geode.internal.cache.BucketRegion;
+import org.apache.geode.internal.cache.EventID;
+import org.apache.geode.internal.cache.ForceReattemptException;
+import org.apache.geode.internal.cache.PartitionedRegion;
+import org.apache.geode.internal.cache.PartitionedRegionHelper;
+import org.apache.geode.internal.cache.RegionEventImpl;
+import org.apache.geode.internal.logging.log4j.LogMarker;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.SerializationContext;
+import org.apache.geode.logging.internal.log4j.api.LogService;
+
+public class ClearPRMessage extends PartitionMessageWithDirectReply {
+  private static final Logger logger = LogService.getLogger();
+
+  private RegionEventImpl regionEvent;
+
+  private Integer bucketId;
+
+  /** The time in ms to wait for a lock to be obtained during doLocalClear() */
+  public static final int LOCK_WAIT_TIMEOUT_MS = 1000;
+  public static final String BUCKET_NON_PRIMARY_MESSAGE =
+      "The bucket region on target member is no longer primary";
+  public static final String BUCKET_REGION_LOCK_UNAVAILABLE_MESSAGE =
+      "A lock for the bucket region could not be obtained.";
+  public static final String EXCEPTION_THROWN_DURING_CLEAR_OPERATION =
+      "An exception was thrown during the local clear operation: ";
+
+  /**
+   * state from operateOnRegion that must be preserved for transmission from the waiting pool
+   */
+  transient boolean result = false;
+
+  /**
+   * Empty constructor to satisfy {@link DataSerializer}requirements
+   */
+  public ClearPRMessage() {}
+
+  public ClearPRMessage(int bucketId) {
+    this.bucketId = bucketId;
+
+    // These are both used by the parent class, but don't apply to this message type
+    this.notificationOnly = false;
+    this.posDup = false;
+  }
+
+  public void setRegionEvent(RegionEventImpl event) {
+    regionEvent = event;
+  }
+
+  public void initMessage(PartitionedRegion region, Set<InternalDistributedMember> recipients,
+      DirectReplyProcessor replyProcessor) {
+    this.resetRecipients();
+    if (recipients != null) {
+      setRecipients(recipients);
+    }
+    this.regionId = region.getPRId();
+    this.processor = replyProcessor;
+    this.processorId = replyProcessor == null ? 0 : replyProcessor.getProcessorId();
+    if (replyProcessor != null) {
+      replyProcessor.enableSevereAlertProcessing();
+    }
+  }
+
+  @Override
+  public boolean isSevereAlertCompatible() {
+    // allow forced-disconnect processing for all cache op messages
+    return true;
+  }
+
+  public RegionEventImpl getRegionEvent() {
+    return regionEvent;
+  }
+
+  public ClearResponse send(DistributedMember recipient, PartitionedRegion region)
+      throws ForceReattemptException {
+    Set<InternalDistributedMember> recipients =
+        Collections.singleton((InternalDistributedMember) recipient);
+    ClearResponse clearResponse = new ClearResponse(region.getSystem(), recipients);
+    initMessage(region, recipients, clearResponse);
+    if (logger.isDebugEnabled()) {
+      logger.debug("ClearPRMessage.send: recipient is {}, msg is {}", recipient, this);
+    }
+
+    Set<InternalDistributedMember> failures = region.getDistributionManager().putOutgoing(this);
+    if (failures != null && failures.size() > 0) {
+      throw new ForceReattemptException("Failed sending <" + this + ">");
+    }
+    return clearResponse;
+  }
+
+  @Override
+  public int getDSFID() {
+    return PR_CLEAR_MESSAGE;
+  }
+
+  @Override
+  public void toData(DataOutput out, SerializationContext context) throws IOException {
+    super.toData(out, context);
+    if (bucketId == null) {
+      InternalDataSerializer.writeSignedVL(-1, out);
+    } else {
+      InternalDataSerializer.writeSignedVL(bucketId, out);
+    }
+    DataSerializer.writeObject(regionEvent, out);
+  }
+
+  @Override
+  public void fromData(DataInput in, DeserializationContext context)
+      throws IOException, ClassNotFoundException {
+    super.fromData(in, context);
+    this.bucketId = (int) InternalDataSerializer.readSignedVL(in);
+    this.regionEvent = DataSerializer.readObject(in);
+  }
+
+  @Override
+  public EventID getEventID() {
+    return regionEvent.getEventId();
+  }
+
+  /**
+   * This method is called upon receipt and make the desired changes to the PartitionedRegion Note:
+   * It is very important that this message does NOT cause any deadlocks as the sender will wait
+   * indefinitely for the acknowledgement
+   */
+  @Override
+  @VisibleForTesting
+  protected boolean operateOnPartitionedRegion(ClusterDistributionManager distributionManager,
+      PartitionedRegion region, long startTime) {
+    try {
+      result = doLocalClear(region);
+    } catch (ForceReattemptException ex) {
+      sendReply(getSender(), getProcessorId(), distributionManager, new ReplyException(ex), region,
+          startTime);
+      return false;
+    }
+    sendReply(getSender(), getProcessorId(), distributionManager, null, region, startTime);
+    return false;
+  }
+
+  public boolean doLocalClear(PartitionedRegion region) throws ForceReattemptException {
+    // Retrieve local bucket region which matches target bucketId
+    BucketRegion bucketRegion = region.getDataStore().getInitializedBucketForId(null, bucketId);
+
+    // Check if we are primary, throw exception if not
+    if (!bucketRegion.isPrimary()) {
+      throw new ForceReattemptException(BUCKET_NON_PRIMARY_MESSAGE);
+    }
+
+    DistributedLockService lockService = getPartitionRegionLockService();
+    String lockName = bucketRegion.getFullPath();
+    try {
+      boolean locked = lockService.lock(lockName, LOCK_WAIT_TIMEOUT_MS, -1);
+
+      if (!locked) {
+        throw new ForceReattemptException(BUCKET_REGION_LOCK_UNAVAILABLE_MESSAGE);
+      }
+
+      // Double check if we are still primary, as this could have changed between our first check
+      // and obtaining the lock
+      if (!bucketRegion.isPrimary()) {
+        throw new ForceReattemptException(BUCKET_NON_PRIMARY_MESSAGE);
+      }
+
+      try {
+        bucketRegion.cmnClearRegion(regionEvent, true, true);
+      } catch (Exception ex) {
+        throw new ForceReattemptException(
+            EXCEPTION_THROWN_DURING_CLEAR_OPERATION + ex.getClass().getName(), ex);
+      }
+
+    } finally {
+      lockService.unlock(lockName);
+    }
+
+    return true;
+  }
+
+  // Extracted for testing
+  protected DistributedLockService getPartitionRegionLockService() {
+    return DistributedLockService
+        .getServiceNamed(PartitionedRegionHelper.PARTITION_LOCK_SERVICE_NAME);
+  }
+
+  @Override
+  public boolean canStartRemoteTransaction() {
+    return false;
+  }
+
+  @Override
+  protected void sendReply(InternalDistributedMember member, int processorId,
+      DistributionManager distributionManager, ReplyException ex,
+      PartitionedRegion partitionedRegion, long startTime) {
+    if (partitionedRegion != null) {
+      if (startTime > 0) {
+        partitionedRegion.getPrStats().endPartitionMessagesProcessing(startTime);
+      }
+    }
+    ClearReplyMessage.send(member, processorId, getReplySender(distributionManager), this.result,
+        ex);
+  }
+
+  @Override
+  protected void appendFields(StringBuilder buff) {
+    super.appendFields(buff);
+    buff.append("; bucketId=").append(this.bucketId);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder buff = new StringBuilder();
+    String className = getClass().getName();
+    buff.append(className.substring(className.indexOf(PN_TOKEN) + PN_TOKEN.length())); // partition.<foo>
+    buff.append("(prid="); // make sure this is the first one
+    buff.append(this.regionId);
+
+    // Append name, if we have it
+    String name = null;
+    try {
+      PartitionedRegion region = PartitionedRegion.getPRFromId(this.regionId);
+      if (region != null) {
+        name = region.getFullPath();
+      }
+    } catch (Exception ignore) {
+      /* ignored */
+    }
+    if (name != null) {
+      buff.append(" (name = \"").append(name).append("\")");
+    }
+
+    appendFields(buff);
+    buff.append(" ,distTx=");
+    buff.append(this.isTransactionDistributed);
+    buff.append(")");
+    return buff.toString();
+  }
+
+  public static class ClearReplyMessage extends ReplyMessage {
+    /** Result of the Clear operation */
+    boolean result;
+
+    @Override
+    public boolean getInlineProcess() {
+      return true;
+    }
+
+    /**
+     * Empty constructor to conform to DataSerializable interface
+     */
+    @SuppressWarnings("unused")
+    public ClearReplyMessage() {}
+
+    private ClearReplyMessage(int processorId, boolean result, ReplyException ex) {
+      super();
+      this.result = result;
+      setProcessorId(processorId);
+      setException(ex);
+    }
+
+    /** Send an ack */
+    public static void send(InternalDistributedMember recipient, int processorId,
+        ReplySender replySender,
+        boolean result, ReplyException ex) {
+      Assert.assertTrue(recipient != null, "ClearReplyMessage NULL reply message");
+      ClearReplyMessage message = new ClearReplyMessage(processorId, result, ex);
+      message.setRecipient(recipient);
+      replySender.putOutgoing(message);
+    }
+
+    /**
+     * Processes this message. This method is invoked by the receiver of the message.
+     *
+     * @param distributionManager the distribution manager that is processing the message.
+     */
+    @Override
+    public void process(final DistributionManager distributionManager,
+        final ReplyProcessor21 replyProcessor) {
+      final long startTime = getTimestamp();
+      if (replyProcessor == null) {
+        if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
+          logger.trace(LogMarker.DM_VERBOSE, "{}: processor not found", this);
+        }
+        return;
+      }
+      if (replyProcessor instanceof ClearResponse) {
+        ((ClearResponse) replyProcessor).setResponse(this);
+      }
+      replyProcessor.process(this);
+
+      if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
+        logger.trace(LogMarker.DM_VERBOSE, "{} processed {}", replyProcessor, this);
+      }
+      distributionManager.getStats().incReplyMessageTime(NanoTimer.getTime() - startTime);
+    }
+
+    @Override
+    public int getDSFID() {
+      return PR_CLEAR_REPLY_MESSAGE;
+    }
+
+    @Override
+    public void fromData(DataInput in,
+        DeserializationContext context) throws IOException, ClassNotFoundException {
+      super.fromData(in, context);
+      this.result = in.readBoolean();
+    }
+
+    @Override
+    public void toData(DataOutput out,
+        SerializationContext context) throws IOException {
+      super.toData(out, context);
+      out.writeBoolean(this.result);
+    }
+
+    @Override
+    public String toString() {
+      return "ClearReplyMessage " + "processorid=" + this.processorId + " returning " + this.result
+          + " exception=" + getException();
+    }
+  }
+
+  /**
+   * A processor to capture the value returned by {@link ClearPRMessage}
+   */
+  public static class ClearResponse extends PartitionResponse {
+    private volatile boolean returnValue;
+
+    public ClearResponse(InternalDistributedSystem distributedSystem,
+        Set<InternalDistributedMember> recipients) {
+      super(distributedSystem, recipients, false);
+    }
+
+    public void setResponse(ClearReplyMessage response) {
+      this.returnValue = response.result;
+    }
+
+    /**
+     * @return the result of the remote clear operation
+     * @throws ForceReattemptException if the peer is no longer available
+     * @throws CacheException if the peer generates an error
+     */
+    public boolean waitForResult() throws CacheException, ForceReattemptException {
+      waitForCacheException();
+      return this.returnValue;
+    }
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java
index 72e6657..c7cf5a6 100755
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java
@@ -14,7 +14,9 @@
  */
 package org.apache.geode.internal.cache;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.anyLong;
@@ -31,7 +33,10 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import org.junit.Test;
+
 import org.apache.geode.cache.RegionAttributes;
+import org.apache.geode.internal.cache.versions.RegionVersionVector;
 import org.apache.geode.internal.statistics.StatisticsClock;
 
 public class BucketRegionJUnitTest extends DistributedRegionJUnitTest {
@@ -128,4 +133,76 @@ public class BucketRegionJUnitTest extends DistributedRegionJUnitTest {
     }
   }
 
+  @Test
+  public void cmnClearRegionWillDoNothingIfNotPrimary() {
+    RegionEventImpl event = createClearRegionEvent();
+    BucketRegion region = (BucketRegion) event.getRegion();
+    BucketAdvisor ba = mock(BucketAdvisor.class);
+    RegionVersionVector rvv = mock(RegionVersionVector.class);
+    doReturn(rvv).when(region).getVersionVector();
+    doReturn(ba).when(region).getBucketAdvisor();
+    when(ba.isPrimary()).thenReturn(false);
+    region.cmnClearRegion(event, true, true);
+    verify(region, never()).clearRegionLocally(eq(event), eq(true), eq(rvv));
+  }
+
+  @Test
+  public void cmnClearRegionCalledOnPrimary() {
+    RegionEventImpl event = createClearRegionEvent();
+    BucketRegion region = (BucketRegion) event.getRegion();
+    BucketAdvisor ba = mock(BucketAdvisor.class);
+    RegionVersionVector rvv = mock(RegionVersionVector.class);
+    doReturn(rvv).when(region).getVersionVector();
+    doReturn(true).when(region).getConcurrencyChecksEnabled();
+    doReturn(ba).when(region).getBucketAdvisor();
+    doNothing().when(region).distributeClearOperation(any(), any(), any());
+    doNothing().when(region).lockLocallyForClear(any(), any(), any());
+    doNothing().when(region).clearRegionLocally(event, true, null);
+    when(ba.isPrimary()).thenReturn(true);
+    region.cmnClearRegion(event, true, true);
+    verify(region, times(1)).clearRegionLocally(eq(event), eq(true), eq(null));
+  }
+
+  @Test
+  public void clearWillUseNullAsRVVWhenConcurrencyCheckDisabled() {
+    RegionEventImpl event = createClearRegionEvent();
+    BucketRegion region = (BucketRegion) event.getRegion();
+    BucketAdvisor ba = mock(BucketAdvisor.class);
+    doReturn(false).when(region).getConcurrencyChecksEnabled();
+    doReturn(ba).when(region).getBucketAdvisor();
+    doNothing().when(region).distributeClearOperation(any(), any(), any());
+    doNothing().when(region).lockLocallyForClear(any(), any(), any());
+    doNothing().when(region).clearRegionLocally(event, true, null);
+    when(ba.isPrimary()).thenReturn(true);
+    region.cmnClearRegion(event, true, true);
+    verify(region, times(1)).clearRegionLocally(eq(event), eq(true), eq(null));
+  }
+
+  @Test
+  public void obtainWriteLocksForClearInBRShouldNotDistribute() {
+    RegionEventImpl event = createClearRegionEvent();
+    BucketRegion region = (BucketRegion) event.getRegion();
+    doNothing().when(region).lockLocallyForClear(any(), any(), any());
+    region.obtainWriteLocksForClear(event, null);
+    assertTrue(region.isUsedForPartitionedRegionBucket());
+  }
+
+  @Test
+  public void updateSizeToZeroOnClearBucketRegion() {
+    RegionEventImpl event = createClearRegionEvent();
+    BucketRegion region = (BucketRegion) event.getRegion();
+    PartitionedRegion pr = region.getPartitionedRegion();
+    PartitionedRegionDataStore prds = mock(PartitionedRegionDataStore.class);
+    PartitionedRegionStats prStats = mock(PartitionedRegionStats.class);
+    when(pr.getPrStats()).thenReturn(prStats);
+    doNothing().when(prStats).incDataStoreEntryCount(anyInt());
+    doNothing().when(prds).updateMemoryStats(anyInt());
+    when(pr.getDataStore()).thenReturn(prds);
+    region.updateSizeOnCreate("key1", 20);
+    long sizeBeforeClear = region.getTotalBytes();
+    assertEquals(20, sizeBeforeClear);
+    region.updateSizeOnClearRegion((int) sizeBeforeClear);
+    long sizeAfterClear = region.getTotalBytes();
+    assertEquals(0, sizeAfterClear);
+  }
 }
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/DistributedRegionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/DistributedRegionJUnitTest.java
index 9fbd8fc..ca53ced 100755
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/DistributedRegionJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/DistributedRegionJUnitTest.java
@@ -14,6 +14,7 @@
  */
 package org.apache.geode.internal.cache;
 
+import static org.apache.geode.internal.Assert.fail;
 import static org.apache.geode.internal.statistics.StatisticsClockFactory.disabledClock;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertFalse;
@@ -53,6 +54,14 @@ public class DistributedRegionJUnitTest
   @Override
   protected void setInternalRegionArguments(InternalRegionArguments ira) {}
 
+  protected RegionEventImpl createClearRegionEvent() {
+    DistributedRegion region = prepare(true, true);
+    DistributedMember member = mock(DistributedMember.class);
+    RegionEventImpl regionEvent = new RegionEventImpl(region, Operation.REGION_CLEAR, null, false,
+        member, true);
+    return regionEvent;
+  }
+
   @Override
   protected DistributedRegion createAndDefineRegion(boolean isConcurrencyChecksEnabled,
       RegionAttributes ra, InternalRegionArguments ira, GemFireCacheImpl cache,
@@ -246,4 +255,13 @@ public class DistributedRegionJUnitTest
     region.basicBridgeReplace("key1", "value1", false, null, client, true, clientEvent);
     assertThat(clientEvent.getVersionTag().equals(tag));
   }
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void localClearIsNotSupportedOnReplicatedRegion() {
+    RegionEventImpl event = createClearRegionEvent();
+    DistributedRegion region = (DistributedRegion) event.getRegion();
+    region.basicLocalClear(event);
+    fail("Expect UnsupportedOperationException");
+  }
+
 }
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java
new file mode 100644
index 0000000..2cf5231
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/partitioned/ClearPRMessageTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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.partitioned;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.distributed.DistributedLockService;
+import org.apache.geode.distributed.internal.ClusterDistributionManager;
+import org.apache.geode.distributed.internal.DMStats;
+import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.distributed.internal.ReplyException;
+import org.apache.geode.distributed.internal.ReplySender;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.BucketRegion;
+import org.apache.geode.internal.cache.ForceReattemptException;
+import org.apache.geode.internal.cache.PartitionedRegion;
+import org.apache.geode.internal.cache.PartitionedRegionDataStore;
+import org.apache.geode.internal.cache.PartitionedRegionStats;
+
+public class ClearPRMessageTest {
+
+  ClearPRMessage message;
+  PartitionedRegion region;
+  PartitionedRegionDataStore dataStore;
+  BucketRegion bucketRegion;
+
+  @Before
+  public void setup() throws ForceReattemptException {
+    message = spy(new ClearPRMessage());
+    region = mock(PartitionedRegion.class, RETURNS_DEEP_STUBS);
+    dataStore = mock(PartitionedRegionDataStore.class);
+    when(region.getDataStore()).thenReturn(dataStore);
+    bucketRegion = mock(BucketRegion.class);
+    when(dataStore.getInitializedBucketForId(any(), any())).thenReturn(bucketRegion);
+  }
+
+  @Test
+  public void doLocalClearThrowsExceptionWhenBucketIsNotPrimaryAtFirstCheck() {
+    when(bucketRegion.isPrimary()).thenReturn(false);
+
+    assertThatThrownBy(() -> message.doLocalClear(region))
+        .isInstanceOf(ForceReattemptException.class)
+        .hasMessageContaining(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
+  }
+
+  @Test
+  public void doLocalClearThrowsExceptionWhenLockCannotBeObtained() {
+    DistributedLockService mockLockService = mock(DistributedLockService.class);
+    doReturn(mockLockService).when(message).getPartitionRegionLockService();
+
+    when(mockLockService.lock(anyString(), anyLong(), anyLong())).thenReturn(false);
+    when(bucketRegion.isPrimary()).thenReturn(true);
+
+    assertThatThrownBy(() -> message.doLocalClear(region))
+        .isInstanceOf(ForceReattemptException.class)
+        .hasMessageContaining(ClearPRMessage.BUCKET_REGION_LOCK_UNAVAILABLE_MESSAGE);
+  }
+
+  @Test
+  public void doLocalClearThrowsExceptionWhenBucketIsNotPrimaryAfterObtainingLock() {
+    DistributedLockService mockLockService = mock(DistributedLockService.class);
+    doReturn(mockLockService).when(message).getPartitionRegionLockService();
+
+    // Be primary on the first check, then be not primary on the second check
+    when(bucketRegion.isPrimary()).thenReturn(true).thenReturn(false);
+    when(mockLockService.lock(any(), anyLong(), anyLong())).thenReturn(true);
+
+    assertThatThrownBy(() -> message.doLocalClear(region))
+        .isInstanceOf(ForceReattemptException.class)
+        .hasMessageContaining(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
+    // Confirm that we actually obtained and released the lock
+    verify(mockLockService, times(1)).lock(any(), anyLong(), anyLong());
+    verify(mockLockService, times(1)).unlock(any());
+  }
+
+  @Test
+  public void doLocalClearThrowsForceReattemptExceptionWhenAnExceptionIsThrownDuringClearOperation() {
+    DistributedLockService mockLockService = mock(DistributedLockService.class);
+    doReturn(mockLockService).when(message).getPartitionRegionLockService();
+    NullPointerException exception = new NullPointerException("Error encountered");
+    doThrow(exception).when(bucketRegion).cmnClearRegion(any(), anyBoolean(), anyBoolean());
+
+    // Be primary on the first check, then be not primary on the second check
+    when(bucketRegion.isPrimary()).thenReturn(true);
+    when(mockLockService.lock(any(), anyLong(), anyLong())).thenReturn(true);
+
+    assertThatThrownBy(() -> message.doLocalClear(region))
+        .isInstanceOf(ForceReattemptException.class)
+        .hasMessageContaining(ClearPRMessage.EXCEPTION_THROWN_DURING_CLEAR_OPERATION);
+
+    // Confirm that cmnClearRegion was called
+    verify(bucketRegion, times(1)).cmnClearRegion(any(), anyBoolean(), anyBoolean());
+  }
+
+  @Test
+  public void doLocalClearInvokesCmnClearRegionWhenBucketIsPrimaryAndLockIsObtained()
+      throws ForceReattemptException {
+    DistributedLockService mockLockService = mock(DistributedLockService.class);
+    doReturn(mockLockService).when(message).getPartitionRegionLockService();
+
+
+    // Be primary on the first check, then be not primary on the second check
+    when(bucketRegion.isPrimary()).thenReturn(true);
+    when(mockLockService.lock(any(), anyLong(), anyLong())).thenReturn(true);
+    assertThat(message.doLocalClear(region)).isTrue();
+
+    // Confirm that cmnClearRegion was called
+    verify(bucketRegion, times(1)).cmnClearRegion(any(), anyBoolean(), anyBoolean());
+
+    // Confirm that we actually obtained and released the lock
+    verify(mockLockService, times(1)).lock(any(), anyLong(), anyLong());
+    verify(mockLockService, times(1)).unlock(any());
+  }
+
+  @Test
+  public void initMessageSetsReplyProcessorCorrectlyWithDefinedReplyProcessor() {
+    InternalDistributedMember sender = mock(InternalDistributedMember.class);
+
+    Set<InternalDistributedMember> recipients = new HashSet<>();
+    recipients.add(sender);
+
+    ClearPRMessage.ClearResponse mockProcessor = mock(ClearPRMessage.ClearResponse.class);
+    int mockProcessorId = 5;
+    when(mockProcessor.getProcessorId()).thenReturn(mockProcessorId);
+
+    message.initMessage(region, recipients, mockProcessor);
+
+    verify(mockProcessor, times(1)).enableSevereAlertProcessing();
+    assertThat(message.getProcessorId()).isEqualTo(mockProcessorId);
+  }
+
+  @Test
+  public void initMessageSetsProcessorIdToZeroWithNullProcessor() {
+    message.initMessage(region, null, null);
+
+    assertThat(message.getProcessorId()).isEqualTo(0);
+  }
+
+  @Test
+  public void sendThrowsExceptionIfPutOutgoingMethodReturnsNonNullSetOfFailures() {
+    InternalDistributedMember recipient = mock(InternalDistributedMember.class);
+
+    DistributionManager distributionManager = mock(DistributionManager.class);
+    when(region.getDistributionManager()).thenReturn(distributionManager);
+
+    doNothing().when(message).initMessage(any(), any(), any());
+    Set<InternalDistributedMember> failures = new HashSet<>();
+    failures.add(recipient);
+
+    when(distributionManager.putOutgoing(message)).thenReturn(failures);
+
+    assertThatThrownBy(() -> message.send(recipient, region))
+        .isInstanceOf(ForceReattemptException.class)
+        .hasMessageContaining("Failed sending <" + message + ">");
+  }
+
+  @SuppressWarnings("ResultOfMethodCallIgnored")
+  @Test
+  public void operateOnPartitionedRegionCallsSendReplyWithNoExceptionWhenDoLocalClearSucceeds()
+      throws ForceReattemptException {
+    ClusterDistributionManager distributionManager = mock(ClusterDistributionManager.class);
+    InternalDistributedMember sender = mock(InternalDistributedMember.class);
+    int processorId = 1000;
+    int startTime = 0;
+
+    doReturn(true).when(message).doLocalClear(region);
+    doReturn(sender).when(message).getSender();
+    doReturn(processorId).when(message).getProcessorId();
+
+    // We don't want to deal with mocking the behavior of sendReply() in this test, so we mock it to
+    // do nothing and verify later that it was called with proper input
+    doNothing().when(message).sendReply(any(), anyInt(), any(), any(), any(), anyLong());
+
+    message.operateOnPartitionedRegion(distributionManager, region, startTime);
+
+    verify(message, times(1)).sendReply(sender, processorId, distributionManager, null, region,
+        startTime);
+  }
+
+  @SuppressWarnings("ResultOfMethodCallIgnored")
+  @Test
+  public void operateOnPartitionedRegionCallsSendReplyWithExceptionWhenDoLocalClearFailsWithException()
+      throws ForceReattemptException {
+    ClusterDistributionManager distributionManager = mock(ClusterDistributionManager.class);
+    InternalDistributedMember sender = mock(InternalDistributedMember.class);
+    int processorId = 1000;
+    int startTime = 0;
+    ForceReattemptException exception =
+        new ForceReattemptException(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
+
+    doThrow(exception).when(message).doLocalClear(region);
+    doReturn(sender).when(message).getSender();
+    doReturn(processorId).when(message).getProcessorId();
+
+    // We don't want to deal with mocking the behavior of sendReply() in this test, so we mock it to
+    // do nothing and verify later that it was called with proper input
+    doNothing().when(message).sendReply(any(), anyInt(), any(), any(), any(), anyLong());
+
+    message.operateOnPartitionedRegion(distributionManager, region, startTime);
+
+    verify(message, times(1)).sendReply(any(), anyInt(), any(), notNull(), any(), anyLong());
+  }
+
+  @Test
+  public void sendReplyEndsMessageProcessingIfWeHaveARegionAndHaveStartedProcessing() {
+    DistributionManager distributionManager = mock(DistributionManager.class);
+    InternalDistributedMember recipient = mock(InternalDistributedMember.class);
+    PartitionedRegionStats partitionedRegionStats = mock(PartitionedRegionStats.class);
+    when(region.getPrStats()).thenReturn(partitionedRegionStats);
+
+    int processorId = 1000;
+    int startTime = 10000;
+    ReplyException exception = new ReplyException(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
+
+    ReplySender replySender = mock(ReplySender.class);
+    doReturn(replySender).when(message).getReplySender(distributionManager);
+
+    message.sendReply(recipient, processorId, distributionManager, exception, region, startTime);
+
+    verify(partitionedRegionStats, times(1)).endPartitionMessagesProcessing(startTime);
+  }
+
+  @Test
+  public void sendReplyDoesNotEndMessageProcessingIfStartTimeIsZero() {
+    DistributionManager distributionManager = mock(DistributionManager.class);
+    InternalDistributedMember recipient = mock(InternalDistributedMember.class);
+    PartitionedRegionStats partitionedRegionStats = mock(PartitionedRegionStats.class);
+    when(region.getPrStats()).thenReturn(partitionedRegionStats);
+
+    int processorId = 1000;
+    int startTime = 0;
+    ReplyException exception = new ReplyException(ClearPRMessage.BUCKET_NON_PRIMARY_MESSAGE);
+
+    ReplySender replySender = mock(ReplySender.class);
+    doReturn(replySender).when(message).getReplySender(distributionManager);
+
+    message.sendReply(recipient, processorId, distributionManager, exception, region, startTime);
+
+    verify(partitionedRegionStats, times(0)).endPartitionMessagesProcessing(startTime);
+  }
+
+  @Test
+  public void clearReplyMessageProcessCallsSetResponseIfReplyProcessorIsInstanceOfClearResponse() {
+    DistributionManager distributionManager = mock(DistributionManager.class);
+    DMStats mockStats = mock(DMStats.class);
+    when(distributionManager.getStats()).thenReturn(mockStats);
+    ClearPRMessage.ClearReplyMessage clearReplyMessage = new ClearPRMessage.ClearReplyMessage();
+    ClearPRMessage.ClearResponse mockProcessor = mock(ClearPRMessage.ClearResponse.class);
+
+    clearReplyMessage.process(distributionManager, mockProcessor);
+
+    verify(mockProcessor, times(1)).setResponse(clearReplyMessage);
+  }
+}
diff --git a/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java b/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
index bf4dd99..7eabedb 100644
--- a/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
+++ b/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
@@ -57,6 +57,9 @@ public interface DataSerializableFixedID extends SerializationVersions, BasicSer
   // NOTE, codes < -65536 will take 4 bytes to serialize
   // NOTE, codes < -128 will take 2 bytes to serialize
 
+  short PR_CLEAR_REPLY_MESSAGE = -164;
+  short PR_CLEAR_MESSAGE = -163;
+
   short DISTRIBUTED_PING_MESSAGE = -162;
 
   short REGION_REDUNDANCY_STATUS = -161;


[geode] 09/11: GEODE-7894: Moving expiry tasks to AbstractRegion.

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 359c3bfe4d263464b282c4aa0825cd75ee8292ad
Author: Nabarun Nag <na...@cs.wisc.edu>
AuthorDate: Mon May 11 13:44:56 2020 -0700

    GEODE-7894: Moving expiry tasks to AbstractRegion.
---
 .../src/main/java/org/apache/geode/internal/cache/AbstractRegion.java  | 1 +
 .../src/main/java/org/apache/geode/internal/cache/LocalRegion.java     | 3 ---
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java
index 0364e17..ca75bf2 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java
@@ -113,6 +113,7 @@ public abstract class AbstractRegion implements InternalRegion, AttributesMutato
   private static final Logger logger = LogService.getLogger();
   private final ReentrantReadWriteLock readWriteLockForCacheLoader = new ReentrantReadWriteLock();
   private final ReentrantReadWriteLock readWriteLockForCacheWriter = new ReentrantReadWriteLock();
+  @VisibleForTesting
   protected final ConcurrentHashMap<RegionEntry, EntryExpiryTask> entryExpiryTasks =
       new ConcurrentHashMap<>();
   /**
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
index dcf35fa..f43fa24 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
@@ -325,9 +325,6 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
    */
   private int txRefCount;
 
-  @VisibleForTesting
-  final ConcurrentHashMap<RegionEntry, EntryExpiryTask> entryExpiryTasks =
-      new ConcurrentHashMap<>();
 
   private volatile boolean regionInvalid;
 


[geode] 11/11: GEODE-7678 (2nd PR) - Support for cache-listener and client-notification for Partitioned Region Clear operation (#5124)

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 8ae9f298136f679f817c45354b1246901ef7e66c
Author: agingade <ag...@pivotal.io>
AuthorDate: Wed May 20 16:08:07 2020 -0700

    GEODE-7678 (2nd PR) - Support for cache-listener and client-notification for Partitioned Region Clear operation  (#5124)
    
    * GEODE-7678: Add support for cache listener and client notification for PR clear
    
    The changes are made to PR clear messaging and locking mechanism to preserve
    cache-listener and client-events ordering during concurrent cache operation
    while clear in progress.
---
 .../integrationTest/resources/assembly_content.txt |   1 +
 .../cache/PRCacheListenerDistributedTest.java      | 250 +++++++++++-
 .../ReplicateCacheListenerDistributedTest.java     | 111 +++++-
 ...ionedRegionAfterClearNotificationDUnitTest.java | 372 ++++++++++++++++++
 .../cache/PartitionedRegionClearDUnitTest.java     |   1 -
 ...titionedRegionClearWithExpirationDUnitTest.java |  69 ++--
 ...itionedRegionClearWithExpirationDUnitTest.java} |  58 +--
 .../cache/PartitionedRegionIntegrationTest.java    |  45 +++
 .../codeAnalysis/sanctionedDataSerializables.txt   |   8 +
 .../PartitionedRegionPartialClearException.java    |  37 ++
 .../main/java/org/apache/geode/cache/Region.java   |   4 +-
 .../org/apache/geode/internal/DSFIDFactory.java    |   5 +
 .../apache/geode/internal/cache/BucketAdvisor.java |   2 +-
 .../apache/geode/internal/cache/BucketRegion.java  |  17 +-
 .../internal/cache/DistributedClearOperation.java  |  10 +-
 .../geode/internal/cache/DistributedRegion.java    |   9 +-
 .../geode/internal/cache/InternalRegion.java       |   3 +
 .../apache/geode/internal/cache/LocalRegion.java   |   3 +-
 .../geode/internal/cache/PartitionedRegion.java    | 217 ++---------
 .../internal/cache/PartitionedRegionClear.java     | 419 +++++++++++++++++++++
 .../cache/PartitionedRegionClearMessage.java       | 287 ++++++++++++++
 .../internal/cache/PartitionedRegionDataStore.java |   8 +
 .../internal/cache/partitioned/RegionAdvisor.java  |  11 +
 .../sanctioned-geode-core-serializables.txt        |   2 +
 .../internal/cache/BucketRegionJUnitTest.java      |   4 +-
 .../internal/cache/PartitionedRegionTest.java      |  39 --
 .../serialization/DataSerializableFixedID.java     |   2 +
 27 files changed, 1679 insertions(+), 315 deletions(-)

diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index e53df01..2e3e322 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -221,6 +221,7 @@ javadoc/org/apache/geode/cache/PartitionAttributes.html
 javadoc/org/apache/geode/cache/PartitionAttributesFactory.html
 javadoc/org/apache/geode/cache/PartitionResolver.html
 javadoc/org/apache/geode/cache/PartitionedRegionDistributionException.html
+javadoc/org/apache/geode/cache/PartitionedRegionPartialClearException.html
 javadoc/org/apache/geode/cache/PartitionedRegionStorageException.html
 javadoc/org/apache/geode/cache/Region.Entry.html
 javadoc/org/apache/geode/cache/Region.html
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/cache/PRCacheListenerDistributedTest.java b/geode-core/src/distributedTest/java/org/apache/geode/cache/PRCacheListenerDistributedTest.java
index 559def7..f4a9ac9 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/cache/PRCacheListenerDistributedTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/cache/PRCacheListenerDistributedTest.java
@@ -14,14 +14,21 @@
  */
 package org.apache.geode.cache;
 
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.apache.geode.test.dunit.VM.getVMCount;
+import static org.assertj.core.api.Assertions.assertThat;
+
 import java.util.Arrays;
+import java.util.Collection;
 
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 import org.junit.runners.Parameterized.UseParametersRunnerFactory;
 
+import org.apache.geode.logging.internal.log4j.api.LogService;
 import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
 
 /**
@@ -38,28 +45,60 @@ import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactor
 @SuppressWarnings("serial")
 public class PRCacheListenerDistributedTest extends ReplicateCacheListenerDistributedTest {
 
-  @Parameters(name = "{index}: redundancy={0}")
-  public static Iterable<Integer> data() {
-    return Arrays.asList(0, 3);
+  @Parameters
+  public static Collection<Object[]> data() {
+    return Arrays.asList(new Object[][] {
+        {1, Boolean.FALSE},
+        {3, Boolean.TRUE},
+    });
   }
 
   @Parameter
   public int redundancy;
 
+  @Parameter(1)
+  public Boolean withData;
+
   @Override
   protected Region<String, Integer> createRegion(final String name,
       final CacheListener<String, Integer> listener) {
+    return createPartitionedRegion(name, listener, false);
+  }
+
+  protected Region<String, Integer> createAccessorRegion(final String name,
+      final CacheListener<String, Integer> listener) {
+    return createPartitionedRegion(name, listener, true);
+  }
+
+  private Region<String, Integer> createPartitionedRegion(String name,
+      CacheListener<String, Integer> listener, boolean accessor) {
+    LogService.getLogger()
+        .info("Params [Redundancy: " + redundancy + " withData:" + withData + "]");
     PartitionAttributesFactory<String, Integer> paf = new PartitionAttributesFactory<>();
     paf.setRedundantCopies(redundancy);
 
+    if (accessor) {
+      paf.setLocalMaxMemory(0);
+    }
     RegionFactory<String, Integer> regionFactory = cacheRule.getCache().createRegionFactory();
-    regionFactory.addCacheListener(listener);
+    if (listener != null) {
+      regionFactory.addCacheListener(listener);
+    }
     regionFactory.setDataPolicy(DataPolicy.PARTITION);
     regionFactory.setPartitionAttributes(paf.create());
 
     return regionFactory.create(name);
   }
 
+  private void withData(Region region) {
+    if (withData) {
+      // Fewer buckets.
+      // Covers case where node doesn't have any buckets depending on redundancy.
+      region.put("key1", "value1");
+      region.put("key2", "value2");
+    }
+  }
+
   @Override
   protected int expectedCreates() {
     return 1;
@@ -79,4 +118,207 @@ public class PRCacheListenerDistributedTest extends ReplicateCacheListenerDistri
   protected int expectedDestroys() {
     return 1;
   }
+
+  @Test
+  public void afterRegionDestroyIsInvokedInEveryMember() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, listener);
+
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, listener));
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY)).isEqualTo(expectedRegionDestroys());
+  }
+
+  @Test
+  public void afterRegionDestroyIsInvokedOnNodeWithListener() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, listener);
+
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionDestroyIsInvokedOnRemoteNodeWithListener() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, null);
+
+    getVM(0).invoke(() -> {
+      createRegion(regionName, listener);
+    });
+
+    for (int i = 1; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionDestroyIsInvokedOnAccessorAndDataMembers() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createAccessorRegion(regionName, listener);
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, listener));
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY))
+        .isGreaterThanOrEqualTo(expectedRegionDestroys());
+  }
+
+  @Test
+  public void afterRegionDestroyIsInvokedOnAccessor() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createAccessorRegion(regionName, listener);
+
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionDestroyIsInvokedOnNonAccessor() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createAccessorRegion(regionName, null);
+    getVM(0).invoke(() -> {
+      createRegion(regionName, listener);
+    });
+    for (int i = 1; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionClearIsInvokedInEveryMember() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, listener);
+
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, listener));
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(expectedClears());
+  }
+
+  @Test
+  public void afterClearIsInvokedOnNodeWithListener() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, listener);
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionClearIsInvokedOnRemoteNodeWithListener() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, null);
+    getVM(0).invoke(() -> {
+      createRegion(regionName, listener);
+    });
+    for (int i = 1; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionClearIsInvokedOnAccessorAndDataMembers() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createAccessorRegion(regionName, listener);
+
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, listener));
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(expectedClears());
+  }
+
+  @Test
+  public void afterRegionClearIsInvokedOnAccessor() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createAccessorRegion(regionName, listener);
+
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(1);
+  }
+
+  @Test
+  public void afterRegionClearIsInvokedOnNonAccessor() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createAccessorRegion(regionName, null);
+
+    getVM(0).invoke(() -> {
+      createRegion(regionName, listener);
+    });
+    for (int i = 1; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        withData(createRegion(regionName, null));
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(1);
+  }
+
 }
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/cache/ReplicateCacheListenerDistributedTest.java b/geode-core/src/distributedTest/java/org/apache/geode/cache/ReplicateCacheListenerDistributedTest.java
index b0e1894..227c813 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/cache/ReplicateCacheListenerDistributedTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/cache/ReplicateCacheListenerDistributedTest.java
@@ -51,13 +51,15 @@ public class ReplicateCacheListenerDistributedTest implements Serializable {
   private static final String UPDATES = "UPDATES";
   private static final String INVALIDATES = "INVALIDATES";
   private static final String DESTROYS = "DESTROYS";
+  protected static final String CLEAR = "CLEAR";
+  protected static final String REGION_DESTROY = "REGION_DESTROY";
 
   private static final int ENTRY_VALUE = 0;
   private static final int UPDATED_ENTRY_VALUE = 1;
 
   private static final String KEY = "key-1";
 
-  private String regionName;
+  protected String regionName;
 
   @Rule
   public DistributedRule distributedRule = new DistributedRule();
@@ -82,6 +84,8 @@ public class ReplicateCacheListenerDistributedTest implements Serializable {
     sharedCountersRule.initialize(DESTROYS);
     sharedCountersRule.initialize(INVALIDATES);
     sharedCountersRule.initialize(UPDATES);
+    sharedCountersRule.initialize(CLEAR);
+    sharedCountersRule.initialize(REGION_DESTROY);
   }
 
   @Test
@@ -148,6 +152,36 @@ public class ReplicateCacheListenerDistributedTest implements Serializable {
     assertThat(sharedCountersRule.getTotal(DESTROYS)).isEqualTo(expectedDestroys());
   }
 
+  @Test
+  public void afterClearIsInvokedInEveryMember() {
+    CacheListener<String, Integer> listener = new ClearCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, listener);
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        createRegion(regionName, listener);
+      });
+    }
+
+    region.clear();
+
+    assertThat(sharedCountersRule.getTotal(CLEAR)).isEqualTo(expectedClears());
+  }
+
+  @Test
+  public void afterRegionDestroyIsInvokedInEveryMember() {
+    CacheListener<String, Integer> listener = new RegionDestroyCountingCacheListener();
+    Region<String, Integer> region = createRegion(regionName, listener);
+    for (int i = 0; i < getVMCount(); i++) {
+      getVM(i).invoke(() -> {
+        createRegion(regionName, listener);
+      });
+    }
+
+    region.destroyRegion();
+
+    assertThat(sharedCountersRule.getTotal(REGION_DESTROY)).isEqualTo(expectedRegionDestroys());
+  }
+
   protected Region<String, Integer> createRegion(final String name,
       final CacheListener<String, Integer> listener) {
     RegionFactory<String, Integer> regionFactory = cacheRule.getCache().createRegionFactory();
@@ -174,6 +208,14 @@ public class ReplicateCacheListenerDistributedTest implements Serializable {
     return getVMCount() + 1;
   }
 
+  protected int expectedClears() {
+    return getVMCount() + 1;
+  }
+
+  protected int expectedRegionDestroys() {
+    return getVMCount() + 1;
+  }
+
   /**
    * Overridden within tests to increment shared counters.
    */
@@ -283,7 +325,12 @@ public class ReplicateCacheListenerDistributedTest implements Serializable {
 
     @Override
     public void afterCreate(final EntryEvent<String, Integer> event) {
-      // ignore
+      sharedCountersRule.increment(CREATES);
+    }
+
+    @Override
+    public void afterUpdate(final EntryEvent<String, Integer> event) {
+      sharedCountersRule.increment(UPDATES);
     }
 
     @Override
@@ -302,4 +349,64 @@ public class ReplicateCacheListenerDistributedTest implements Serializable {
       errorCollector.checkThat(event.getNewValue(), nullValue());
     }
   }
+
+  protected class ClearCountingCacheListener extends BaseCacheListener {
+
+    @Override
+    public void afterCreate(final EntryEvent<String, Integer> event) {
+      sharedCountersRule.increment(CREATES);
+    }
+
+    @Override
+    public void afterUpdate(final EntryEvent<String, Integer> event) {
+      sharedCountersRule.increment(UPDATES);
+    }
+
+    @Override
+    public void afterRegionClear(RegionEvent<String, Integer> event) {
+
+      sharedCountersRule.increment(CLEAR);
+      if (!event.getRegion().getAttributes().getDataPolicy().withPartitioning()) {
+        if (event.isOriginRemote()) {
+          errorCollector.checkThat(event.getDistributedMember(),
+              not(cacheRule.getSystem().getDistributedMember()));
+        } else {
+          errorCollector.checkThat(event.getDistributedMember(),
+              equalTo(cacheRule.getSystem().getDistributedMember()));
+        }
+      }
+      errorCollector.checkThat(event.getOperation(), equalTo(Operation.REGION_CLEAR));
+      errorCollector.checkThat(event.getRegion().getName(), equalTo(regionName));
+    }
+  }
+
+  protected class RegionDestroyCountingCacheListener extends BaseCacheListener {
+
+    @Override
+    public void afterCreate(final EntryEvent<String, Integer> event) {
+      sharedCountersRule.increment(CREATES);
+    }
+
+    @Override
+    public void afterUpdate(final EntryEvent<String, Integer> event) {
+      sharedCountersRule.increment(UPDATES);
+    }
+
+    @Override
+    public void afterRegionDestroy(final RegionEvent<String, Integer> event) {
+      sharedCountersRule.increment(REGION_DESTROY);
+
+      if (!event.getRegion().getAttributes().getDataPolicy().withPartitioning()) {
+        if (event.isOriginRemote()) {
+          errorCollector.checkThat(event.getDistributedMember(),
+              not(cacheRule.getSystem().getDistributedMember()));
+        } else {
+          errorCollector.checkThat(event.getDistributedMember(),
+              equalTo(cacheRule.getSystem().getDistributedMember()));
+        }
+      }
+      errorCollector.checkThat(event.getOperation(), equalTo(Operation.REGION_DESTROY));
+      errorCollector.checkThat(event.getRegion().getName(), equalTo(regionName));
+    }
+  }
 }
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionAfterClearNotificationDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionAfterClearNotificationDUnitTest.java
new file mode 100644
index 0000000..237b6a8
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionAfterClearNotificationDUnitTest.java
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.internal.cache;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getCache;
+import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getClientCache;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.IntStream;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.cache.InterestResultPolicy;
+import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionEvent;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.cache.util.CacheListenerAdapter;
+import org.apache.geode.distributed.internal.ClusterDistributionManager;
+import org.apache.geode.distributed.internal.DistributionMessage;
+import org.apache.geode.distributed.internal.DistributionMessageObserver;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.AsyncInvocation;
+import org.apache.geode.test.dunit.DUnitBlackboard;
+import org.apache.geode.test.dunit.SerializableCallableIF;
+import org.apache.geode.test.dunit.rules.ClientVM;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+public class PartitionedRegionAfterClearNotificationDUnitTest implements Serializable {
+  protected static final String REGION_NAME = "testPR";
+  protected static final int NUM_ENTRIES = 100;
+
+  protected int locatorPort;
+  protected MemberVM locator;
+  protected MemberVM dataStore1;
+  protected MemberVM dataStore2;
+  protected MemberVM dataStore3;
+  protected MemberVM accessor;
+
+  protected ClientVM client1;
+  protected ClientVM client2;
+
+  private static volatile DUnitBlackboard blackboard;
+
+  @Rule
+  public ClusterStartupRule cluster = new ClusterStartupRule(7);
+
+  @Before
+  public void setUp() throws Exception {
+    locator = cluster.startLocatorVM(0);
+    locatorPort = locator.getPort();
+    dataStore1 = cluster.startServerVM(1, getProperties(), locatorPort);
+    dataStore2 = cluster.startServerVM(2, getProperties(), locatorPort);
+    dataStore3 = cluster.startServerVM(3, getProperties(), locatorPort);
+    accessor = cluster.startServerVM(4, getProperties(), locatorPort);
+
+    client1 = cluster.startClientVM(5,
+        c -> c.withPoolSubscription(true).withLocatorConnection((locatorPort)));
+    client2 = cluster.startClientVM(6,
+        c -> c.withPoolSubscription(true).withLocatorConnection((locatorPort)));
+
+    dataStore1.invoke(this::initDataStore);
+    dataStore2.invoke(this::initDataStore);
+    dataStore3.invoke(this::initDataStore);
+    accessor.invoke(this::initAccessor);
+
+    getBlackboard().initBlackboard();
+  }
+
+  protected RegionShortcut getRegionShortCut() {
+    return RegionShortcut.PARTITION_REDUNDANT;
+  }
+
+  protected Properties getProperties() {
+    Properties properties = new Properties();
+    return properties;
+  }
+
+  private Region getRegion(boolean isClient) {
+    if (isClient) {
+      return getClientCache().getRegion(REGION_NAME);
+    } else {
+      return getCache().getRegion(REGION_NAME);
+    }
+  }
+
+  private void verifyRegionSize(boolean isClient, int expectedNum) {
+    GeodeAwaitility.await()
+        .untilAsserted(() -> assertThat(getRegion(isClient).size()).isEqualTo(expectedNum));
+  }
+
+  private void initClientCache() {
+    Region region = getClientCache().createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY)
+        .create(REGION_NAME);
+    region.registerInterestForAllKeys(InterestResultPolicy.KEYS);
+  }
+
+  private void stopServers() {
+    List<CacheServer> cacheServers = getCache().getCacheServers();
+    for (CacheServer server : cacheServers) {
+      server.stop();
+    }
+  }
+
+  private void initDataStore() {
+    getCache().createRegionFactory(getRegionShortCut())
+        .setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(10).create())
+        .addCacheListener(new CountingCacheListener())
+        .create(REGION_NAME);
+  }
+
+  private void initAccessor() {
+    RegionShortcut shortcut = getRegionShortCut();
+    getCache().createRegionFactory(shortcut)
+        .setPartitionAttributes(
+            new PartitionAttributesFactory().setTotalNumBuckets(10).setLocalMaxMemory(0).create())
+        .addCacheListener(new CountingCacheListener())
+        .create(REGION_NAME);
+  }
+
+  private void feed(boolean isClient) {
+    Region region = getRegion(isClient);
+    IntStream.range(0, NUM_ENTRIES).forEach(i -> region.put(i, "value" + i));
+  }
+
+  private void verifyServerRegionSize(int expectedNum) {
+    accessor.invoke(() -> verifyRegionSize(false, expectedNum));
+    dataStore1.invoke(() -> verifyRegionSize(false, expectedNum));
+    dataStore2.invoke(() -> verifyRegionSize(false, expectedNum));
+    dataStore3.invoke(() -> verifyRegionSize(false, expectedNum));
+  }
+
+  private void verifyClientRegionSize(int expectedNum) {
+    client1.invoke(() -> verifyRegionSize(true, expectedNum));
+    client2.invoke(() -> verifyRegionSize(true, expectedNum));
+  }
+
+  private void verifyCacheListenerTriggerCount(MemberVM serverVM) {
+    SerializableCallableIF<Integer> getListenerTriggerCount = () -> {
+      CountingCacheListener countingCacheListener =
+          (CountingCacheListener) getRegion(false).getAttributes()
+              .getCacheListeners()[0];
+      return countingCacheListener.getClears();
+    };
+
+    int count = accessor.invoke(getListenerTriggerCount)
+        + dataStore1.invoke(getListenerTriggerCount)
+        + dataStore2.invoke(getListenerTriggerCount)
+        + dataStore3.invoke(getListenerTriggerCount);
+    assertThat(count).isEqualTo(4);
+
+    if (serverVM != null) {
+      assertThat(serverVM.invoke(getListenerTriggerCount)).isEqualTo(1);
+    }
+  }
+
+  @Test
+  public void invokeClearOnDataStoreAndVerifyListenerCount() {
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+
+    dataStore1.invoke(() -> getRegion(false).clear());
+
+    verifyServerRegionSize(0);
+    verifyCacheListenerTriggerCount(dataStore1);
+  }
+
+  @Test
+  public void invokeClearOnAccessorAndVerifyListenerCount() {
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+    accessor.invoke(() -> getRegion(false).clear());
+    verifyServerRegionSize(0);
+    verifyCacheListenerTriggerCount(accessor);
+  }
+
+  @Test
+  public void invokeClearFromClientAndVerifyListenerCount() {
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    client1.invoke(() -> feed(true));
+    verifyClientRegionSize(NUM_ENTRIES);
+    verifyServerRegionSize(NUM_ENTRIES);
+
+    client1.invoke(() -> getRegion(true).clear());
+
+    verifyServerRegionSize(0);
+    verifyClientRegionSize(0);
+    verifyCacheListenerTriggerCount(null);
+  }
+
+  @Test
+  public void invokeClearFromClientWithAccessorAsServer() {
+    dataStore1.invoke(this::stopServers);
+    dataStore2.invoke(this::stopServers);
+    dataStore3.invoke(this::stopServers);
+
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    client1.invoke(() -> feed(true));
+    verifyClientRegionSize(NUM_ENTRIES);
+    verifyServerRegionSize(NUM_ENTRIES);
+
+    client1.invoke(() -> getRegion(true).clear());
+
+    verifyServerRegionSize(0);
+    verifyClientRegionSize(0);
+    verifyCacheListenerTriggerCount(null);
+  }
+
+  @Test
+  public void invokeClearFromDataStoreWithClientInterest() {
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+
+    dataStore1.invoke(() -> getRegion(false).clear());
+
+    verifyServerRegionSize(0);
+    verifyCacheListenerTriggerCount(dataStore1);
+  }
+
+  @Test(expected = AssertionError.class)
+  public void verifyTheLocksAreClearedWhenMemberDepartsAfterTakingClearLockOnRemoteMembers()
+      throws Exception {
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+    dataStore2.invoke(() -> DistributionMessageObserver.setInstance(
+        testHookToKillMemberCallingClearBeforeMessageProcessed()));
+
+    AsyncInvocation ds1ClearAsync = dataStore1.invokeAsync(() -> getRegion(false).clear());
+
+    getBlackboard().waitForGate("CLOSE_CACHE", 30, SECONDS);
+
+    dataStore1.invoke(() -> getCache().close());
+    getBlackboard().signalGate("CACHE_CLOSED");
+
+    // This should not be blocked.
+    dataStore2.invoke(() -> feed(false));
+    dataStore3.invoke(() -> feed(false));
+
+    dataStore2.invoke(() -> verifyRegionSize(false, NUM_ENTRIES));
+    dataStore3.invoke(() -> verifyRegionSize(false, NUM_ENTRIES));
+
+    ds1ClearAsync.await();
+  }
+
+  @Test
+  public void verifyTheLocksAreClearedWhenMemberDepartsAfterTakingClearLockOnRemoteMembersAfterMessageProcessed()
+      throws Exception {
+    client1.invoke(this::initClientCache);
+    client2.invoke(this::initClientCache);
+
+    accessor.invoke(() -> feed(false));
+    verifyServerRegionSize(NUM_ENTRIES);
+
+    dataStore2.invoke(() -> DistributionMessageObserver.setInstance(
+        testHookToKillMemberCallingClearAfterMessageProcessed()));
+
+    AsyncInvocation ds1ClearAsync = dataStore1.invokeAsync(() -> getRegion(false).clear());
+
+    getBlackboard().waitForGate("CLOSE_CACHE", 30, SECONDS);
+
+    dataStore1.invoke(() -> getCache().close());
+    getBlackboard().signalGate("CACHE_CLOSED");
+
+    // This should not be blocked.
+    dataStore2.invoke(() -> feed(false));
+    dataStore3.invoke(() -> feed(false));
+
+    dataStore2.invoke(() -> verifyRegionSize(false, NUM_ENTRIES));
+    dataStore3.invoke(() -> verifyRegionSize(false, NUM_ENTRIES));
+
+    ds1ClearAsync.await();
+  }
+
+
+  private static class CountingCacheListener extends CacheListenerAdapter {
+    private final AtomicInteger clears = new AtomicInteger();
+
+    @Override
+    public void afterRegionClear(RegionEvent event) {
+      clears.incrementAndGet();
+    }
+
+    int getClears() {
+      return clears.get();
+
+    }
+  }
+
+  private DistributionMessageObserver testHookToKillMemberCallingClearBeforeMessageProcessed() {
+    return new DistributionMessageObserver() {
+
+      @Override
+      public void beforeProcessMessage(ClusterDistributionManager dm, DistributionMessage message) {
+        if (message instanceof PartitionedRegionClearMessage) {
+          if (((PartitionedRegionClearMessage) message)
+              .getOp() == PartitionedRegionClearMessage.OperationType.OP_LOCK_FOR_PR_CLEAR) {
+            DistributionMessageObserver.setInstance(null);
+            getBlackboard().signalGate("CLOSE_CACHE");
+            try {
+              getBlackboard().waitForGate("CACHE_CLOSED", 30, SECONDS);
+              GeodeAwaitility.await().untilAsserted(
+                  () -> assertThat(dm.isCurrentMember(message.getSender())).isFalse());
+            } catch (TimeoutException | InterruptedException e) {
+              throw new RuntimeException("Failed waiting for signal.");
+            }
+          }
+        }
+      }
+    };
+  }
+
+  private DistributionMessageObserver testHookToKillMemberCallingClearAfterMessageProcessed() {
+    return new DistributionMessageObserver() {
+      @Override
+      public void afterProcessMessage(ClusterDistributionManager dm, DistributionMessage message) {
+        if (message instanceof PartitionedRegionClearMessage) {
+          if (((PartitionedRegionClearMessage) message)
+              .getOp() == PartitionedRegionClearMessage.OperationType.OP_LOCK_FOR_PR_CLEAR) {
+            DistributionMessageObserver.setInstance(null);
+            getBlackboard().signalGate("CLOSE_CACHE");
+            try {
+              getBlackboard().waitForGate("CACHE_CLOSED", 30, SECONDS);
+            } catch (TimeoutException | InterruptedException e) {
+              throw new RuntimeException("Failed waiting for signal.");
+            }
+          }
+        }
+      }
+    };
+  }
+
+  private static DUnitBlackboard getBlackboard() {
+    if (blackboard == null) {
+      blackboard = new DUnitBlackboard();
+    }
+    return blackboard;
+  }
+
+}
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
index e2e04eb..a3b311c 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearDUnitTest.java
@@ -80,7 +80,6 @@ public class PartitionedRegionClearDUnitTest implements Serializable {
 
   protected Properties getProperties() {
     Properties properties = new Properties();
-    properties.setProperty("log-level", "info");
     return properties;
   }
 
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
index 7f3dff9..dfc9470 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
@@ -17,12 +17,8 @@ package org.apache.geode.internal.cache;
 import static org.apache.geode.cache.ExpirationAction.DESTROY;
 import static org.apache.geode.cache.RegionShortcut.PARTITION;
 import static org.apache.geode.cache.RegionShortcut.PARTITION_OVERFLOW;
-import static org.apache.geode.cache.RegionShortcut.PARTITION_PERSISTENT;
-import static org.apache.geode.cache.RegionShortcut.PARTITION_PERSISTENT_OVERFLOW;
 import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT;
 import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT_OVERFLOW;
-import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT_PERSISTENT;
-import static org.apache.geode.cache.RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW;
 import static org.apache.geode.internal.util.ArrayUtils.asList;
 import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
 import static org.apache.geode.test.dunit.VM.getVM;
@@ -53,6 +49,7 @@ import org.apache.geode.cache.CacheWriterException;
 import org.apache.geode.cache.ExpirationAttributes;
 import org.apache.geode.cache.PartitionAttributes;
 import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.PartitionedRegionPartialClearException;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.RegionEvent;
 import org.apache.geode.cache.RegionShortcut;
@@ -75,7 +72,8 @@ import org.apache.geode.test.dunit.rules.DistributedRule;
 @RunWith(JUnitParamsRunner.class)
 public class PartitionedRegionClearWithExpirationDUnitTest implements Serializable {
   private static final Integer BUCKETS = 13;
-  private static final Integer EXPIRATION_TIME = 30;
+  private static final Integer EXPIRATION_TIME = 5 * 60;
+  private static final Integer SMALL_EXPIRATION_TIME = 10;
   private static final String REGION_NAME = "PartitionedRegion";
 
   @Rule
@@ -106,11 +104,6 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
         PARTITION_OVERFLOW,
         PARTITION_REDUNDANT,
         PARTITION_REDUNDANT_OVERFLOW,
-
-        PARTITION_PERSISTENT,
-        PARTITION_PERSISTENT_OVERFLOW,
-        PARTITION_REDUNDANT_PERSISTENT,
-        PARTITION_REDUNDANT_PERSISTENT_OVERFLOW
     };
   }
 
@@ -134,26 +127,8 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
     accessor = getVM(TestVM.ACCESSOR.vmNumber);
   }
 
-  private RegionShortcut getRegionAccessorShortcut(RegionShortcut dataStoreRegionShortcut) {
-    if (dataStoreRegionShortcut.isPersistent()) {
-      switch (dataStoreRegionShortcut) {
-        case PARTITION_PERSISTENT:
-          return PARTITION;
-        case PARTITION_PERSISTENT_OVERFLOW:
-          return PARTITION_OVERFLOW;
-        case PARTITION_REDUNDANT_PERSISTENT:
-          return PARTITION_REDUNDANT;
-        case PARTITION_REDUNDANT_PERSISTENT_OVERFLOW:
-          return PARTITION_REDUNDANT_OVERFLOW;
-      }
-    }
-
-    return dataStoreRegionShortcut;
-  }
-
   private void initAccessor(RegionShortcut regionShortcut,
       ExpirationAttributes expirationAttributes) {
-    RegionShortcut accessorShortcut = getRegionAccessorShortcut(regionShortcut);
     PartitionAttributes<String, String> attributes =
         new PartitionAttributesFactory<String, String>()
             .setTotalNumBuckets(BUCKETS)
@@ -161,7 +136,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
             .create();
 
     cacheRule.getCache()
-        .<String, String>createRegionFactory(accessorShortcut)
+        .<String, String>createRegionFactory(regionShortcut)
         .setPartitionAttributes(attributes)
         .setEntryTimeToLive(expirationAttributes)
         .setEntryIdleTimeout(expirationAttributes)
@@ -281,6 +256,19 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
     }));
   }
 
+  private void doClear() {
+    Cache cache = cacheRule.getCache();
+    boolean retry;
+    do {
+      retry = false;
+      try {
+        cache.getRegion(REGION_NAME).clear();
+      } catch (PartitionedRegionPartialClearException | CacheWriterException ex) {
+        retry = true;
+      }
+    } while (retry);
+  }
+
   /**
    * The test does the following (clear coordinator and region type are parametrized):
    * - Populates the Partition Region (entries have expiration).
@@ -303,10 +291,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
     populateRegion(accessor, entries, asList(accessor, server1, server2));
 
     // Clear the region.
-    getVM(coordinatorVM.vmNumber).invoke(() -> {
-      Cache cache = cacheRule.getCache();
-      cache.getRegion(REGION_NAME).clear();
-    });
+    getVM(coordinatorVM.vmNumber).invoke(() -> doClear());
 
     // Assert all expiration tasks were cancelled and none were executed.
     asList(server1, server2).forEach(vm -> vm.invoke(() -> {
@@ -323,7 +308,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
 
     // Assert Region Buckets are consistent and region is empty,
     accessor.invoke(this::assertRegionBucketsConsistency);
-    assertRegionIsEmpty(asList(accessor, server1, server1));
+    assertRegionIsEmpty(asList(accessor, server1, server2));
   }
 
   /**
@@ -344,7 +329,8 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
   public void clearShouldFailWhenCoordinatorMemberIsBouncedAndExpirationTasksShouldSurvive(
       RegionShortcut regionShortcut) {
     final int entries = 1000;
-    ExpirationAttributes expirationAttributes = new ExpirationAttributes(EXPIRATION_TIME, DESTROY);
+    ExpirationAttributes expirationAttributes =
+        new ExpirationAttributes(SMALL_EXPIRATION_TIME, DESTROY);
     parametrizedSetup(regionShortcut, expirationAttributes);
     populateRegion(accessor, entries, asList(accessor, server1, server2));
     registerVMKillerAsCacheWriter(Collections.singletonList(server1));
@@ -408,22 +394,21 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
   @TestCaseName("[{index}] {method}(Coordinator:{0}, RegionType:{1})")
   public void clearShouldSucceedAndRemoveRegisteredExpirationTasksWhenNonCoordinatorMemberIsBounced(
       TestVM coordinatorVM, RegionShortcut regionShortcut) {
-    final int entries = 1500;
+    final int entries = 500;
+
+    RegionShortcut rs = regionShortcut;
     ExpirationAttributes expirationAttributes = new ExpirationAttributes(EXPIRATION_TIME, DESTROY);
     parametrizedSetup(regionShortcut, expirationAttributes);
     registerVMKillerAsCacheWriter(Collections.singletonList(server2));
     populateRegion(accessor, entries, asList(accessor, server1, server2));
 
     // Clear the region.
-    getVM(coordinatorVM.vmNumber).invoke(() -> {
-      Cache cache = cacheRule.getCache();
-      cache.getRegion(REGION_NAME).clear();
-    });
+    getVM(coordinatorVM.vmNumber).invoke(() -> doClear());
 
     // Wait for member to get back online and assign buckets.
     server2.invoke(() -> {
       cacheRule.createCache();
-      initDataStore(regionShortcut, expirationAttributes);
+      initDataStore(rs, expirationAttributes);
       await().untilAsserted(
           () -> assertThat(InternalDistributedSystem.getConnectedInstance()).isNotNull());
       PartitionRegionHelper.assignBucketsToPartitions(cacheRule.getCache().getRegion(REGION_NAME));
@@ -460,7 +445,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
 
     // Assert Region Buckets are consistent and region is empty,
     accessor.invoke(this::assertRegionBucketsConsistency);
-    assertRegionIsEmpty(asList(accessor, server1, server1));
+    assertRegionIsEmpty(asList(accessor, server1, server2));
   }
 
   /**
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PersistentPartitionedRegionClearWithExpirationDUnitTest.java
similarity index 93%
copy from geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
copy to geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PersistentPartitionedRegionClearWithExpirationDUnitTest.java
index 7f3dff9..f6f25bd 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PartitionedRegionClearWithExpirationDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/PersistentPartitionedRegionClearWithExpirationDUnitTest.java
@@ -53,6 +53,7 @@ import org.apache.geode.cache.CacheWriterException;
 import org.apache.geode.cache.ExpirationAttributes;
 import org.apache.geode.cache.PartitionAttributes;
 import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.PartitionedRegionPartialClearException;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.RegionEvent;
 import org.apache.geode.cache.RegionShortcut;
@@ -73,9 +74,10 @@ import org.apache.geode.test.dunit.rules.DistributedRule;
  * on the {@link PartitionedRegion} once the operation is executed.
  */
 @RunWith(JUnitParamsRunner.class)
-public class PartitionedRegionClearWithExpirationDUnitTest implements Serializable {
+public class PersistentPartitionedRegionClearWithExpirationDUnitTest implements Serializable {
   private static final Integer BUCKETS = 13;
-  private static final Integer EXPIRATION_TIME = 30;
+  private static final Integer EXPIRATION_TIME = 5 * 60;
+  private static final Integer SMALL_EXPIRATION_TIME = 10;
   private static final String REGION_NAME = "PartitionedRegion";
 
   @Rule
@@ -102,11 +104,6 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
   @SuppressWarnings("unused")
   static RegionShortcut[] regionTypes() {
     return new RegionShortcut[] {
-        PARTITION,
-        PARTITION_OVERFLOW,
-        PARTITION_REDUNDANT,
-        PARTITION_REDUNDANT_OVERFLOW,
-
         PARTITION_PERSISTENT,
         PARTITION_PERSISTENT_OVERFLOW,
         PARTITION_REDUNDANT_PERSISTENT,
@@ -281,6 +278,19 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
     }));
   }
 
+  private void doClear() {
+    Cache cache = cacheRule.getCache();
+    boolean retry;
+    do {
+      retry = false;
+      try {
+        cache.getRegion(REGION_NAME).clear();
+      } catch (PartitionedRegionPartialClearException | CacheWriterException ex) {
+        retry = true;
+      }
+    } while (retry);
+  }
+
   /**
    * The test does the following (clear coordinator and region type are parametrized):
    * - Populates the Partition Region (entries have expiration).
@@ -303,10 +313,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
     populateRegion(accessor, entries, asList(accessor, server1, server2));
 
     // Clear the region.
-    getVM(coordinatorVM.vmNumber).invoke(() -> {
-      Cache cache = cacheRule.getCache();
-      cache.getRegion(REGION_NAME).clear();
-    });
+    getVM(coordinatorVM.vmNumber).invoke(() -> doClear());
 
     // Assert all expiration tasks were cancelled and none were executed.
     asList(server1, server2).forEach(vm -> vm.invoke(() -> {
@@ -323,7 +330,7 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
 
     // Assert Region Buckets are consistent and region is empty,
     accessor.invoke(this::assertRegionBucketsConsistency);
-    assertRegionIsEmpty(asList(accessor, server1, server1));
+    assertRegionIsEmpty(asList(accessor, server1, server2));
   }
 
   /**
@@ -344,7 +351,8 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
   public void clearShouldFailWhenCoordinatorMemberIsBouncedAndExpirationTasksShouldSurvive(
       RegionShortcut regionShortcut) {
     final int entries = 1000;
-    ExpirationAttributes expirationAttributes = new ExpirationAttributes(EXPIRATION_TIME, DESTROY);
+    ExpirationAttributes expirationAttributes =
+        new ExpirationAttributes(SMALL_EXPIRATION_TIME, DESTROY);
     parametrizedSetup(regionShortcut, expirationAttributes);
     populateRegion(accessor, entries, asList(accessor, server1, server2));
     registerVMKillerAsCacheWriter(Collections.singletonList(server1));
@@ -407,23 +415,29 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
   @Parameters(method = "vmsAndRegionTypes")
   @TestCaseName("[{index}] {method}(Coordinator:{0}, RegionType:{1})")
   public void clearShouldSucceedAndRemoveRegisteredExpirationTasksWhenNonCoordinatorMemberIsBounced(
-      TestVM coordinatorVM, RegionShortcut regionShortcut) {
-    final int entries = 1500;
+      TestVM coordinatorVM, RegionShortcut regionShortcut) throws Exception {
+    final int entries = 500;
+    // To avoid partition offline exception without redundancy.
+
+    if (regionShortcut == PARTITION_PERSISTENT) {
+      regionShortcut = PARTITION_REDUNDANT_PERSISTENT;
+    } else if (regionShortcut == PARTITION_PERSISTENT_OVERFLOW) {
+      regionShortcut = PARTITION_REDUNDANT_PERSISTENT_OVERFLOW;
+    }
+
+    final RegionShortcut rs = regionShortcut;
     ExpirationAttributes expirationAttributes = new ExpirationAttributes(EXPIRATION_TIME, DESTROY);
     parametrizedSetup(regionShortcut, expirationAttributes);
     registerVMKillerAsCacheWriter(Collections.singletonList(server2));
     populateRegion(accessor, entries, asList(accessor, server1, server2));
 
     // Clear the region.
-    getVM(coordinatorVM.vmNumber).invoke(() -> {
-      Cache cache = cacheRule.getCache();
-      cache.getRegion(REGION_NAME).clear();
-    });
+    getVM(coordinatorVM.vmNumber).invoke(() -> doClear());
 
     // Wait for member to get back online and assign buckets.
     server2.invoke(() -> {
       cacheRule.createCache();
-      initDataStore(regionShortcut, expirationAttributes);
+      initDataStore(rs, expirationAttributes);
       await().untilAsserted(
           () -> assertThat(InternalDistributedSystem.getConnectedInstance()).isNotNull());
       PartitionRegionHelper.assignBucketsToPartitions(cacheRule.getCache().getRegion(REGION_NAME));
@@ -459,8 +473,8 @@ public class PartitionedRegionClearWithExpirationDUnitTest implements Serializab
     });
 
     // Assert Region Buckets are consistent and region is empty,
-    accessor.invoke(this::assertRegionBucketsConsistency);
-    assertRegionIsEmpty(asList(accessor, server1, server1));
+    // accessor.invoke(this::assertRegionBucketsConsistency);
+    assertRegionIsEmpty(asList(accessor, server1, server2));
   }
 
   /**
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionIntegrationTest.java
index 818a855..933bc39 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionIntegrationTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/PartitionedRegionIntegrationTest.java
@@ -16,15 +16,24 @@
 package org.apache.geode.internal.cache;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
+import java.util.List;
 import java.util.concurrent.ScheduledExecutorService;
 
 import org.junit.Rule;
 import org.junit.Test;
 
+import org.apache.geode.cache.CacheEvent;
 import org.apache.geode.cache.EvictionAction;
 import org.apache.geode.cache.EvictionAttributes;
+import org.apache.geode.cache.Operation;
+import org.apache.geode.cache.Region;
 import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache30.TestCacheListener;
 import org.apache.geode.test.junit.rules.ServerStarterRule;
 
 public class PartitionedRegionIntegrationTest {
@@ -55,4 +64,40 @@ public class PartitionedRegionIntegrationTest {
     ScheduledExecutorService bucketSorter = region.getBucketSorter();
     assertThat(bucketSorter).isNull();
   }
+
+  @Test
+  public void prClearWithDataInvokesCacheListenerAfterClear() {
+    TestCacheListener prCacheListener = new TestCacheListener() {};
+    TestCacheListener spyPRCacheListener = spy(prCacheListener);
+
+    Region region = server.createPartitionRegion("PR1",
+        f -> f.addCacheListener(spyPRCacheListener), f -> f.setTotalNumBuckets(2));
+    region.put("key1", "value2");
+    region.put("key2", "value2");
+    spyPRCacheListener.enableEventHistory();
+
+    region.clear();
+
+    verify(spyPRCacheListener, times(1)).afterRegionClear(any());
+    List cacheEvents = spyPRCacheListener.getEventHistory();
+    assertThat(cacheEvents.size()).isEqualTo(1);
+    assertThat(((CacheEvent) cacheEvents.get(0)).getOperation()).isEqualTo(Operation.REGION_CLEAR);
+  }
+
+  @Test
+  public void prClearWithoutDataInvokesCacheListenerAfterClear() {
+    TestCacheListener prCacheListener = new TestCacheListener() {};
+    TestCacheListener spyPRCacheListener = spy(prCacheListener);
+
+    Region region = server.createPartitionRegion("PR1",
+        f -> f.addCacheListener(spyPRCacheListener), f -> f.setTotalNumBuckets(2));
+    spyPRCacheListener.enableEventHistory();
+
+    region.clear();
+
+    verify(spyPRCacheListener, times(1)).afterRegionClear(any());
+    List cacheEvents = spyPRCacheListener.getEventHistory();
+    assertThat(cacheEvents.size()).isEqualTo(1);
+    assertThat(((CacheEvent) cacheEvents.get(0)).getOperation()).isEqualTo(Operation.REGION_CLEAR);
+  }
 }
diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 25c169b..d295e56 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1154,6 +1154,14 @@ org/apache/geode/internal/cache/PartitionRegionConfig,2
 fromData,207
 toData,178
 
+org/apache/geode/internal/cache/PartitionedRegionClearMessage,2
+fromData,40
+toData,36
+
+org/apache/geode/internal/cache/PartitionedRegionClearMessage$PartitionedRegionClearReplyMessage,2
+fromData,29
+toData,28
+
 org/apache/geode/internal/cache/PoolFactoryImpl$PoolAttributes,2
 fromData,161
 toData,161
diff --git a/geode-core/src/main/java/org/apache/geode/cache/PartitionedRegionPartialClearException.java b/geode-core/src/main/java/org/apache/geode/cache/PartitionedRegionPartialClearException.java
new file mode 100644
index 0000000..1ddb301
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/cache/PartitionedRegionPartialClearException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.cache;
+
+/**
+ * Indicates a failure to perform a distributed clear operation on a Partitioned Region
+ * after multiple attempts. The clear may not have been successfully applied on some of
+ * the members hosting the region.
+ */
+public class PartitionedRegionPartialClearException extends CacheRuntimeException {
+
+  public PartitionedRegionPartialClearException() {}
+
+  public PartitionedRegionPartialClearException(String msg) {
+    super(msg);
+  }
+
+  public PartitionedRegionPartialClearException(String msg, Throwable cause) {
+    super(msg, cause);
+  }
+
+  public PartitionedRegionPartialClearException(Throwable cause) {
+    super(cause);
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/cache/Region.java b/geode-core/src/main/java/org/apache/geode/cache/Region.java
index b6ba670..4707a46 100644
--- a/geode-core/src/main/java/org/apache/geode/cache/Region.java
+++ b/geode-core/src/main/java/org/apache/geode/cache/Region.java
@@ -1304,7 +1304,9 @@ public interface Region<K, V> extends ConcurrentMap<K, V> {
    * @see java.util.Map#clear()
    * @see CacheListener#afterRegionClear
    * @see CacheWriter#beforeRegionClear
-   * @throws UnsupportedOperationException If the region is a partitioned region
+   * @throws PartitionedRegionPartialClearException when data is partially cleared on partitioned
+   *         region. It is caller responsibility to handle the partial data clear either by retrying
+   *         the clear operation or continue working with the partially cleared partitioned region.
    */
   @Override
   void clear();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java b/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java
index c97f391..7bd4da3 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/DSFIDFactory.java
@@ -235,6 +235,7 @@ import org.apache.geode.internal.cache.MemberFunctionStreamingMessage;
 import org.apache.geode.internal.cache.Node;
 import org.apache.geode.internal.cache.PRQueryProcessor;
 import org.apache.geode.internal.cache.PartitionRegionConfig;
+import org.apache.geode.internal.cache.PartitionedRegionClearMessage;
 import org.apache.geode.internal.cache.PreferBytesCachedDeserializable;
 import org.apache.geode.internal.cache.RegionEventImpl;
 import org.apache.geode.internal.cache.ReleaseClearLockMessage;
@@ -679,6 +680,10 @@ public class DSFIDFactory implements DataSerializableFixedID {
     serializer.registerDSFID(PR_DUMP_B2N_REPLY_MESSAGE, DumpB2NReplyMessage.class);
     serializer.registerDSFID(DESTROY_PARTITIONED_REGION_MESSAGE,
         DestroyPartitionedRegionMessage.class);
+    serializer.registerDSFID(CLEAR_PARTITIONED_REGION_MESSAGE,
+        PartitionedRegionClearMessage.class);
+    serializer.registerDSFID(CLEAR_PARTITIONED_REGION_REPLY_MESSAGE,
+        PartitionedRegionClearMessage.PartitionedRegionClearReplyMessage.class);
     serializer.registerDSFID(INVALIDATE_PARTITIONED_REGION_MESSAGE,
         InvalidatePartitionedRegionMessage.class);
     serializer.registerDSFID(COMMIT_PROCESS_QUERY_MESSAGE, CommitProcessQueryMessage.class);
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketAdvisor.java b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketAdvisor.java
index e4045c3..6cba754 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketAdvisor.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketAdvisor.java
@@ -1622,7 +1622,7 @@ public class BucketAdvisor extends CacheDistributionAdvisor {
   /**
    * Returns true if the a primary is known.
    */
-  private boolean hasPrimary() {
+  protected boolean hasPrimary() {
     final byte primaryState = this.primaryState;
     return primaryState == OTHER_PRIMARY_NOT_HOSTING || primaryState == OTHER_PRIMARY_HOSTING
         || primaryState == IS_PRIMARY_HOSTING;
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
index e4fa7ef..c37e1a3 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/BucketRegion.java
@@ -575,8 +575,13 @@ public class BucketRegion extends DistributedRegion implements Bucket {
     // get rvvLock
     Set<InternalDistributedMember> participants =
         getCacheDistributionAdvisor().adviseInvalidateRegion();
+    boolean isLockedAlready = this.partitionedRegion.getPartitionedRegionClear()
+        .isLockedForListenerAndClientNotification();
+
     try {
-      obtainWriteLocksForClear(regionEvent, participants);
+      if (!isLockedAlready) {
+        obtainWriteLocksForClear(regionEvent, participants);
+      }
       // no need to dominate my own rvv.
       // Clear is on going here, there won't be GII for this member
       clearRegionLocally(regionEvent, cacheWrite, null);
@@ -584,7 +589,9 @@ public class BucketRegion extends DistributedRegion implements Bucket {
 
       // TODO: call reindexUserDataRegion if there're lucene indexes
     } finally {
-      releaseWriteLocksForClear(regionEvent, participants);
+      if (!isLockedAlready) {
+        releaseWriteLocksForClear(regionEvent, participants);
+      }
     }
   }
 
@@ -2493,4 +2500,10 @@ public class BucketRegion extends DistributedRegion implements Bucket {
   void checkSameSenderIdsAvailableOnAllNodes() {
     // nothing needed on a bucket region
   }
+
+  @Override
+  protected void basicClear(RegionEventImpl regionEvent) {
+    basicClear(regionEvent, false);
+  }
+
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedClearOperation.java b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedClearOperation.java
index 4396581..25cc2f5 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedClearOperation.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedClearOperation.java
@@ -207,7 +207,7 @@ public class DistributedClearOperation extends DistributedCacheOperation {
     protected boolean operateOnRegion(CacheEvent event, ClusterDistributionManager dm)
         throws EntryNotFoundException {
 
-      DistributedRegion region = (DistributedRegion) event.getRegion();
+      LocalRegion region = (LocalRegion) event.getRegion();
       switch (this.clearOp) {
         case OP_CLEAR:
           region.clearRegionLocally((RegionEventImpl) event, false, this.rvv);
@@ -215,9 +215,11 @@ public class DistributedClearOperation extends DistributedCacheOperation {
           this.appliedOperation = true;
           break;
         case OP_LOCK_FOR_CLEAR:
-          if (region.getDataPolicy().withStorage()) {
-            DistributedClearOperation.regionLocked(this.getSender(), region.getFullPath(), region);
-            region.lockLocallyForClear(dm, this.getSender(), event);
+          if (region.getDataPolicy().withStorage() && region instanceof DistributedRegion) {
+            DistributedRegion distributedRegion = (DistributedRegion) region;
+            DistributedClearOperation.regionLocked(this.getSender(), region.getFullPath(),
+                distributedRegion);
+            distributedRegion.lockLocallyForClear(dm, this.getSender(), event);
           }
           this.appliedOperation = true;
           break;
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
index 84b5a3b..d0035fa 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java
@@ -2130,7 +2130,13 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
    */
   protected void releaseWriteLocksForClear(RegionEventImpl regionEvent,
       Set<InternalDistributedMember> participants) {
+    releaseLockLocallyForClear(regionEvent);
+    if (!isUsedForPartitionedRegionBucket()) {
+      DistributedClearOperation.releaseLocks(regionEvent, participants);
+    }
+  }
 
+  protected void releaseLockLocallyForClear(RegionEventImpl regionEvent) {
     ARMLockTestHook armLockTestHook = getRegionMap().getARMLockTestHook();
     if (armLockTestHook != null) {
       armLockTestHook.beforeRelease(this, regionEvent);
@@ -2140,9 +2146,6 @@ public class DistributedRegion extends LocalRegion implements InternalDistribute
     if (rvv != null) {
       rvv.unlockForClear(getMyId());
     }
-    if (!isUsedForPartitionedRegionBucket()) {
-      DistributedClearOperation.releaseLocks(regionEvent, participants);
-    }
 
     if (armLockTestHook != null) {
       armLockTestHook.afterRelease(this, regionEvent);
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
index 876353f..8ade506 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java
@@ -466,4 +466,7 @@ public interface InternalRegion extends Region, HasCachePerfStats, RegionEntryCo
   boolean isRegionCreateNotified();
 
   void setRegionCreateNotified(boolean notified);
+
+  void clearRegionLocally(RegionEventImpl regionEvent, boolean cacheWrite,
+      RegionVersionVector vector);
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
index f43fa24..f47032a 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
@@ -8456,7 +8456,8 @@ public class LocalRegion extends AbstractRegion implements LoaderHelperFactory,
    * will not take distributedLock. The clear operation will also clear the local transactional
    * entries. The clear operation will have immediate committed state.
    */
-  void clearRegionLocally(RegionEventImpl regionEvent, boolean cacheWrite,
+  @Override
+  public void clearRegionLocally(RegionEventImpl regionEvent, boolean cacheWrite,
       RegionVersionVector vector) {
     final boolean isRvvDebugEnabled = logger.isTraceEnabled(LogMarker.RVV_VERBOSE);
 
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
index f0b2992..653b2ce 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
@@ -322,6 +322,8 @@ public class PartitionedRegion extends LocalRegion
     }
   };
 
+  private final PartitionedRegionClear partitionedRegionClear = new PartitionedRegionClear(this);
+
   /**
    * Global Region for storing PR config ( PRName->PRConfig). This region would be used to resolve
    * PR name conflict.*
@@ -2172,198 +2174,6 @@ public class PartitionedRegion extends LocalRegion
     throw new UnsupportedOperationException();
   }
 
-  @Override
-  void basicClear(RegionEventImpl regionEvent, boolean cacheWrite) {
-    final boolean isDebugEnabled = logger.isDebugEnabled();
-    synchronized (clearLock) {
-      final DistributedLockService lockService = getPartitionedRegionLockService();
-      try {
-        lockService.lock("_clearOperation" + this.getFullPath().replace('/', '_'), -1, -1);
-      } catch (IllegalStateException e) {
-        lockCheckReadiness();
-        throw e;
-      }
-      try {
-        if (cache.isCacheAtShutdownAll()) {
-          throw cache.getCacheClosedException("Cache is shutting down");
-        }
-
-        // do cacheWrite
-        cacheWriteBeforeRegionClear(regionEvent);
-
-        // create ClearPRMessage per bucket
-        List<ClearPRMessage> clearMsgList = createClearPRMessages(regionEvent.getEventId());
-        for (ClearPRMessage clearPRMessage : clearMsgList) {
-          int bucketId = clearPRMessage.getBucketId();
-          checkReadiness();
-          long sendMessagesStartTime = 0;
-          if (isDebugEnabled) {
-            sendMessagesStartTime = System.currentTimeMillis();
-          }
-          try {
-            sendClearMsgByBucket(bucketId, clearPRMessage);
-          } catch (PartitionOfflineException poe) {
-            // TODO add a PartialResultException
-            logger.info("PR.sendClearMsgByBucket encountered PartitionOfflineException at bucket "
-                + bucketId, poe);
-          } catch (Exception e) {
-            logger.info("PR.sendClearMsgByBucket encountered exception at bucket " + bucketId, e);
-          }
-
-          if (isDebugEnabled) {
-            long now = System.currentTimeMillis();
-            logger.debug("PR.sendClearMsgByBucket for bucket {} took {} ms", bucketId,
-                (now - sendMessagesStartTime));
-          }
-          // TODO add psStats
-        }
-      } finally {
-        try {
-          lockService.unlock("_clearOperation" + this.getFullPath().replace('/', '_'));
-        } catch (IllegalStateException e) {
-          lockCheckReadiness();
-        }
-      }
-
-      // notify bridge clients at PR level
-      regionEvent.setEventType(EnumListenerEvent.AFTER_REGION_CLEAR);
-      boolean hasListener = hasListener();
-      if (hasListener) {
-        dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_CLEAR, regionEvent);
-      }
-      notifyBridgeClients(regionEvent);
-      logger.info("Partitioned region {} finsihed clear operation.", this.getFullPath());
-    }
-  }
-
-  void sendClearMsgByBucket(final Integer bucketId, ClearPRMessage clearPRMessage) {
-    RetryTimeKeeper retryTime = null;
-    InternalDistributedMember currentTarget = getNodeForBucketWrite(bucketId, null);
-    if (logger.isDebugEnabled()) {
-      logger.debug("PR.sendClearMsgByBucket:bucket {}'s currentTarget is {}", bucketId,
-          currentTarget);
-    }
-
-    long timeOut = 0;
-    int count = 0;
-    while (true) {
-      switch (count) {
-        case 0:
-          // Note we don't check for DM cancellation in common case.
-          // First time. Assume success, keep going.
-          break;
-        case 1:
-          this.cache.getCancelCriterion().checkCancelInProgress(null);
-          // Second time (first failure). Calculate timeout and keep going.
-          timeOut = System.currentTimeMillis() + this.retryTimeout;
-          break;
-        default:
-          this.cache.getCancelCriterion().checkCancelInProgress(null);
-          // test for timeout
-          long timeLeft = timeOut - System.currentTimeMillis();
-          if (timeLeft < 0) {
-            PRHARedundancyProvider.timedOut(this, null, null, "clear a bucket" + bucketId,
-                this.retryTimeout);
-            // NOTREACHED
-          }
-
-          // Didn't time out. Sleep a bit and then continue
-          boolean interrupted = Thread.interrupted();
-          try {
-            Thread.sleep(PartitionedRegionHelper.DEFAULT_WAIT_PER_RETRY_ITERATION);
-          } catch (InterruptedException ignore) {
-            interrupted = true;
-          } finally {
-            if (interrupted) {
-              Thread.currentThread().interrupt();
-            }
-          }
-          break;
-      } // switch
-      count++;
-
-      if (currentTarget == null) { // pick target
-        checkReadiness();
-        if (retryTime == null) {
-          retryTime = new RetryTimeKeeper(this.retryTimeout);
-        }
-
-        currentTarget = waitForNodeOrCreateBucket(retryTime, null, bucketId, false);
-        if (currentTarget == null) {
-          // the bucket does not exist, no need to clear
-          logger.info("Bucket " + bucketId + " does not contain data, no need to clear");
-          return;
-        } else {
-          if (logger.isDebugEnabled()) {
-            logger.debug("PR.sendClearMsgByBucket: new currentTarget is {}", currentTarget);
-          }
-        }
-
-        // It's possible this is a GemFire thread e.g. ServerConnection
-        // which got to this point because of a distributed system shutdown or
-        // region closure which uses interrupt to break any sleep() or wait() calls
-        // e.g. waitForPrimary or waitForBucketRecovery in which case throw exception
-        checkShutdown();
-        continue;
-      } // pick target
-
-      boolean result = false;
-      try {
-        final boolean isLocal = (this.localMaxMemory > 0) && currentTarget.equals(getMyId());
-        if (isLocal) {
-          result = clearPRMessage.doLocalClear(this);
-        } else {
-          ClearPRMessage.ClearResponse response = clearPRMessage.send(currentTarget, this);
-          if (response != null) {
-            this.prStats.incPartitionMessagesSent();
-            result = response.waitForResult();
-          }
-        }
-        if (result) {
-          return;
-        }
-      } catch (ForceReattemptException fre) {
-        checkReadiness();
-        InternalDistributedMember lastTarget = currentTarget;
-        if (retryTime == null) {
-          retryTime = new RetryTimeKeeper(this.retryTimeout);
-        }
-        currentTarget = getNodeForBucketWrite(bucketId, retryTime);
-        if (lastTarget.equals(currentTarget)) {
-          if (logger.isDebugEnabled()) {
-            logger.debug("PR.sendClearMsgByBucket: Retrying at the same node:{} due to {}",
-                currentTarget, fre.getMessage());
-          }
-          if (retryTime.overMaximum()) {
-            PRHARedundancyProvider.timedOut(this, null, null, "clear a bucket",
-                this.retryTimeout);
-            // NOTREACHED
-          }
-          retryTime.waitToRetryNode();
-        } else {
-          if (logger.isDebugEnabled()) {
-            logger.debug("PR.sendClearMsgByBucket: Old target was {}, Retrying {}", lastTarget,
-                currentTarget);
-          }
-        }
-      }
-
-      // It's possible this is a GemFire thread e.g. ServerConnection
-      // which got to this point because of a distributed system shutdown or
-      // region closure which uses interrupt to break any sleep() or wait()
-      // calls
-      // e.g. waitForPrimary or waitForBucketRecovery in which case throw
-      // exception
-      checkShutdown();
-
-      // If we get here, the attempt failed...
-      if (count == 1) {
-        // TODO prStats add ClearPRMsg retried
-        this.prStats.incPutAllMsgsRetried();
-      }
-    }
-  }
-
   List<ClearPRMessage> createClearPRMessages(EventID eventID) {
     ArrayList<ClearPRMessage> clearMsgList = new ArrayList<>();
     for (int bucketId = 0; bucketId < getTotalNumberOfBuckets(); bucketId++) {
@@ -10436,4 +10246,27 @@ public class PartitionedRegion extends LocalRegion
     this.getSystem().handleResourceEvent(ResourceEvent.REGION_CREATE, this);
     this.regionCreationNotified = true;
   }
+
+  protected PartitionedRegionClear getPartitionedRegionClear() {
+    return partitionedRegionClear;
+  }
+
+  @Override
+  void cmnClearRegion(RegionEventImpl regionEvent, boolean cacheWrite, boolean useRVV) {
+    // Synchronized to avoid other threads invoking clear on this vm/node.
+    synchronized (clearLock) {
+      partitionedRegionClear.doClear(regionEvent, cacheWrite, this);
+    }
+  }
+
+  boolean hasAnyClientsInterested() {
+    // Check local filter
+    if (getFilterProfile() != null && (getFilterProfile().hasInterest() || getFilterProfile()
+        .hasCQs())) {
+      return true;
+    }
+    // check peer server filters
+    return (getRegionAdvisor().hasPRServerWithInterest()
+        || getRegionAdvisor().hasPRServerWithCQs());
+  }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionClear.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionClear.java
new file mode 100644
index 0000000..69277ef
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionClear.java
@@ -0,0 +1,419 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.CancelException;
+import org.apache.geode.cache.CacheWriterException;
+import org.apache.geode.cache.Operation;
+import org.apache.geode.cache.OperationAbortedException;
+import org.apache.geode.cache.PartitionedRegionPartialClearException;
+import org.apache.geode.cache.partition.PartitionRegionHelper;
+import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.distributed.internal.MembershipListener;
+import org.apache.geode.distributed.internal.ReplyException;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.versions.RegionVersionVector;
+import org.apache.geode.logging.internal.log4j.api.LogService;
+
+public class PartitionedRegionClear {
+
+  private static final Logger logger = LogService.getLogger();
+
+  private static final String CLEAR_OPERATION = "_clearOperation";
+
+  private final int retryTime = 2 * 60 * 1000;
+
+  private final PartitionedRegion partitionedRegion;
+
+  private final LockForListenerAndClientNotification lockForListenerAndClientNotification =
+      new LockForListenerAndClientNotification();
+
+  private volatile boolean membershipChange = false;
+
+  public PartitionedRegionClear(PartitionedRegion partitionedRegion) {
+    this.partitionedRegion = partitionedRegion;
+    partitionedRegion.getDistributionManager()
+        .addMembershipListener(new PartitionedRegionClearListener());
+  }
+
+  public boolean isLockedForListenerAndClientNotification() {
+    return lockForListenerAndClientNotification.isLocked();
+  }
+
+  void acquireDistributedClearLock(String clearLock) {
+    try {
+      partitionedRegion.getPartitionedRegionLockService().lock(clearLock, -1, -1);
+    } catch (IllegalStateException e) {
+      partitionedRegion.lockCheckReadiness();
+      throw e;
+    }
+  }
+
+  void releaseDistributedClearLock(String clearLock) {
+    try {
+      partitionedRegion.getPartitionedRegionLockService().unlock(clearLock);
+    } catch (IllegalStateException e) {
+      partitionedRegion.lockCheckReadiness();
+    } catch (Exception ex) {
+      logger.warn("Caught exception while unlocking clear distributed lock. " + ex.getMessage());
+    }
+  }
+
+  void obtainLockForClear(RegionEventImpl event) {
+    obtainClearLockLocal(partitionedRegion.getDistributionManager().getId());
+    sendPartitionedRegionClearMessage(event,
+        PartitionedRegionClearMessage.OperationType.OP_LOCK_FOR_PR_CLEAR);
+  }
+
+  void releaseLockForClear(RegionEventImpl event) {
+    releaseClearLockLocal();
+    sendPartitionedRegionClearMessage(event,
+        PartitionedRegionClearMessage.OperationType.OP_UNLOCK_FOR_PR_CLEAR);
+  }
+
+  List clearRegion(RegionEventImpl regionEvent, boolean cacheWrite,
+      RegionVersionVector vector) {
+    List allBucketsCleared = new ArrayList();
+    allBucketsCleared.addAll(clearRegionLocal(regionEvent));
+    allBucketsCleared.addAll(sendPartitionedRegionClearMessage(regionEvent,
+        PartitionedRegionClearMessage.OperationType.OP_PR_CLEAR));
+    return allBucketsCleared;
+  }
+
+  private void waitForPrimary() {
+    boolean retry;
+    PartitionedRegion.RetryTimeKeeper retryTimer = new PartitionedRegion.RetryTimeKeeper(retryTime);
+    do {
+      retry = false;
+      for (BucketRegion bucketRegion : partitionedRegion.getDataStore()
+          .getAllLocalBucketRegions()) {
+        if (!bucketRegion.getBucketAdvisor().hasPrimary()) {
+          if (retryTimer.overMaximum()) {
+            throw new PartitionedRegionPartialClearException(
+                "Unable to find primary bucket region during clear operation for region: " +
+                    partitionedRegion.getName());
+          }
+          retryTimer.waitForBucketsRecovery();
+          retry = true;
+        }
+      }
+    } while (retry);
+  }
+
+  public ArrayList clearRegionLocal(RegionEventImpl regionEvent) {
+    ArrayList clearedBuckets = new ArrayList();
+    membershipChange = false;
+    // Synchronized to handle the requester departure.
+    synchronized (lockForListenerAndClientNotification) {
+      if (partitionedRegion.getDataStore() != null) {
+        partitionedRegion.getDataStore().lockBucketCreationForRegionClear();
+        try {
+          boolean retry;
+          do {
+            waitForPrimary();
+
+            for (BucketRegion localPrimaryBucketRegion : partitionedRegion.getDataStore()
+                .getAllLocalPrimaryBucketRegions()) {
+              if (localPrimaryBucketRegion.size() > 0) {
+                localPrimaryBucketRegion.clear();
+              }
+              clearedBuckets.add(localPrimaryBucketRegion.getId());
+            }
+
+            if (membershipChange) {
+              membershipChange = false;
+              retry = true;
+            } else {
+              retry = false;
+            }
+
+          } while (retry);
+          doAfterClear(regionEvent);
+        } finally {
+          partitionedRegion.getDataStore().unlockBucketCreationForRegionClear();
+        }
+      } else {
+        // Non data-store with client queue and listener
+        doAfterClear(regionEvent);
+      }
+    }
+    return clearedBuckets;
+  }
+
+  private void doAfterClear(RegionEventImpl regionEvent) {
+    if (partitionedRegion.hasAnyClientsInterested()) {
+      notifyClients(regionEvent);
+    }
+
+    if (partitionedRegion.hasListener()) {
+      partitionedRegion.dispatchListenerEvent(EnumListenerEvent.AFTER_REGION_CLEAR, regionEvent);
+    }
+  }
+
+  void notifyClients(RegionEventImpl event) {
+    // Set client routing information into the event
+    // The clear operation in case of PR is distributed differently
+    // hence the FilterRoutingInfo is set here instead of
+    // DistributedCacheOperation.distribute().
+    event.setEventType(EnumListenerEvent.AFTER_REGION_CLEAR);
+    if (!partitionedRegion.isUsedForMetaRegion() && !partitionedRegion
+        .isUsedForPartitionedRegionAdmin()
+        && !partitionedRegion.isUsedForPartitionedRegionBucket() && !partitionedRegion
+            .isUsedForParallelGatewaySenderQueue()) {
+
+      FilterRoutingInfo localCqFrInfo =
+          partitionedRegion.getFilterProfile().getFilterRoutingInfoPart1(event,
+              FilterProfile.NO_PROFILES, Collections.emptySet());
+
+      FilterRoutingInfo localCqInterestFrInfo =
+          partitionedRegion.getFilterProfile().getFilterRoutingInfoPart2(localCqFrInfo, event);
+
+      if (localCqInterestFrInfo != null) {
+        event.setLocalFilterInfo(localCqInterestFrInfo.getLocalFilterInfo());
+      }
+    }
+    partitionedRegion.notifyBridgeClients(event);
+  }
+
+  protected void obtainClearLockLocal(InternalDistributedMember requester) {
+    synchronized (lockForListenerAndClientNotification) {
+      // Check if the member is still part of the distributed system
+      if (!partitionedRegion.getDistributionManager().isCurrentMember(requester)) {
+        return;
+      }
+
+      lockForListenerAndClientNotification.setLocked(requester);
+      if (partitionedRegion.getDataStore() != null) {
+        for (BucketRegion localPrimaryBucketRegion : partitionedRegion.getDataStore()
+            .getAllLocalPrimaryBucketRegions()) {
+          try {
+            localPrimaryBucketRegion.lockLocallyForClear(partitionedRegion.getDistributionManager(),
+                partitionedRegion.getMyId(), null);
+          } catch (Exception ex) {
+            partitionedRegion.checkClosed();
+          }
+        }
+      }
+    }
+  }
+
+  protected void releaseClearLockLocal() {
+    synchronized (lockForListenerAndClientNotification) {
+      if (lockForListenerAndClientNotification.getLockRequester() == null) {
+        // The member has left.
+        return;
+      }
+      try {
+        if (partitionedRegion.getDataStore() != null) {
+
+          for (BucketRegion localPrimaryBucketRegion : partitionedRegion.getDataStore()
+              .getAllLocalPrimaryBucketRegions()) {
+            try {
+              localPrimaryBucketRegion.releaseLockLocallyForClear(null);
+            } catch (Exception ex) {
+              logger.debug(
+                  "Unable to acquire clear lock for bucket region " + localPrimaryBucketRegion
+                      .getName(),
+                  ex.getMessage());
+              partitionedRegion.checkClosed();
+            }
+          }
+        }
+      } finally {
+        lockForListenerAndClientNotification.setUnLocked();
+      }
+    }
+  }
+
+  private List sendPartitionedRegionClearMessage(RegionEventImpl event,
+      PartitionedRegionClearMessage.OperationType op) {
+    RegionEventImpl eventForLocalClear = (RegionEventImpl) event.clone();
+    eventForLocalClear.setOperation(Operation.REGION_LOCAL_CLEAR);
+
+    do {
+      try {
+        return attemptToSendPartitionedRegionClearMessage(event, op);
+      } catch (ForceReattemptException reattemptException) {
+        // retry
+      }
+    } while (true);
+  }
+
+  private List attemptToSendPartitionedRegionClearMessage(RegionEventImpl event,
+      PartitionedRegionClearMessage.OperationType op)
+      throws ForceReattemptException {
+    List bucketsOperated = null;
+
+    if (partitionedRegion.getPRRoot() == null) {
+      if (logger.isDebugEnabled()) {
+        logger.debug(
+            "Partition region {} failed to initialize. Remove its profile from remote members.",
+            this.partitionedRegion);
+      }
+      new UpdateAttributesProcessor(partitionedRegion, true).distribute(false);
+      return bucketsOperated;
+    }
+
+    final HashSet configRecipients =
+        new HashSet(partitionedRegion.getRegionAdvisor().adviseAllPRNodes());
+
+    try {
+      final PartitionRegionConfig prConfig =
+          partitionedRegion.getPRRoot().get(partitionedRegion.getRegionIdentifier());
+
+      if (prConfig != null) {
+        Iterator itr = prConfig.getNodes().iterator();
+        while (itr.hasNext()) {
+          InternalDistributedMember idm = ((Node) itr.next()).getMemberId();
+          if (!idm.equals(partitionedRegion.getMyId())) {
+            configRecipients.add(idm);
+          }
+        }
+      }
+    } catch (CancelException ignore) {
+      // ignore
+    }
+
+    try {
+      PartitionedRegionClearMessage.PartitionedRegionClearResponse resp =
+          new PartitionedRegionClearMessage.PartitionedRegionClearResponse(
+              partitionedRegion.getSystem(),
+              configRecipients);
+      PartitionedRegionClearMessage partitionedRegionClearMessage =
+          new PartitionedRegionClearMessage(configRecipients, partitionedRegion, resp, op, event);
+      partitionedRegionClearMessage.send();
+
+      resp.waitForRepliesUninterruptibly();
+      bucketsOperated = resp.bucketsCleared;
+
+    } catch (ReplyException e) {
+      Throwable t = e.getCause();
+      if (t instanceof ForceReattemptException) {
+        throw (ForceReattemptException) t;
+      }
+      if (t instanceof PartitionedRegionPartialClearException) {
+        throw new PartitionedRegionPartialClearException(t.getMessage(), t);
+      }
+      logger.warn(
+          "PartitionedRegionClear#sendPartitionedRegionClearMessage: Caught exception during ClearRegionMessage send and waiting for response",
+          e);
+    }
+    return bucketsOperated;
+  }
+
+  void doClear(RegionEventImpl regionEvent, boolean cacheWrite,
+      PartitionedRegion partitionedRegion) {
+    String lockName = CLEAR_OPERATION + partitionedRegion.getDisplayName();
+
+    try {
+      // distributed lock to make sure only one clear op is in progress in the cluster.
+      acquireDistributedClearLock(lockName);
+
+      // Force all primary buckets to be created before clear.
+      PartitionRegionHelper.assignBucketsToPartitions(partitionedRegion);
+
+      // do cacheWrite
+      try {
+        partitionedRegion.cacheWriteBeforeRegionClear(regionEvent);
+      } catch (OperationAbortedException operationAbortedException) {
+        throw new CacheWriterException(operationAbortedException);
+      }
+
+      // Check if there are any listeners or clients interested. If so, then clear write
+      // locks needs to be taken on all local and remote primary buckets in order to
+      // preserve the ordering of client events (for concurrent operations on the region).
+      boolean acquireClearLockForClientNotification =
+          (partitionedRegion.hasAnyClientsInterested() && partitionedRegion.hasListener());
+      if (acquireClearLockForClientNotification) {
+        obtainLockForClear(regionEvent);
+      }
+      try {
+        List bucketsCleared = clearRegion(regionEvent, cacheWrite, null);
+
+        if (partitionedRegion.getTotalNumberOfBuckets() != bucketsCleared.size()) {
+          String message = "Unable to clear all the buckets from the partitioned region "
+              + partitionedRegion.getName()
+              + ", either data (buckets) moved or member departed.";
+
+          logger.warn(message + " expected to clear number of buckets: "
+              + partitionedRegion.getTotalNumberOfBuckets() +
+              " actual cleared: " + bucketsCleared.size());
+
+          throw new PartitionedRegionPartialClearException(message);
+        }
+      } finally {
+        if (acquireClearLockForClientNotification) {
+          releaseLockForClear(regionEvent);
+        }
+      }
+
+    } finally {
+      releaseDistributedClearLock(lockName);
+    }
+  }
+
+  void handleClearFromDepartedMember(InternalDistributedMember departedMember) {
+    if (departedMember.equals(lockForListenerAndClientNotification.getLockRequester())) {
+      synchronized (lockForListenerAndClientNotification) {
+        if (lockForListenerAndClientNotification.getLockRequester() != null) {
+          releaseClearLockLocal();
+        }
+      }
+    }
+  }
+
+  class LockForListenerAndClientNotification {
+
+    private boolean locked = false;
+
+    private InternalDistributedMember lockRequester;
+
+    synchronized void setLocked(InternalDistributedMember member) {
+      locked = true;
+      lockRequester = member;
+    }
+
+    synchronized void setUnLocked() {
+      locked = false;
+      lockRequester = null;
+    }
+
+    synchronized boolean isLocked() {
+      return locked;
+    }
+
+    synchronized InternalDistributedMember getLockRequester() {
+      return lockRequester;
+    }
+  }
+
+  protected class PartitionedRegionClearListener implements MembershipListener {
+
+    @Override
+    public synchronized void memberDeparted(DistributionManager distributionManager,
+        InternalDistributedMember id, boolean crashed) {
+      membershipChange = true;
+      handleClearFromDepartedMember(id);
+    }
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionClearMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionClearMessage.java
new file mode 100755
index 0000000..b66ab44
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionClearMessage.java
@@ -0,0 +1,287 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.geode.DataSerializer;
+import org.apache.geode.cache.CacheException;
+import org.apache.geode.cache.Operation;
+import org.apache.geode.distributed.internal.ClusterDistributionManager;
+import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.distributed.internal.DistributionMessage;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.distributed.internal.ReplyException;
+import org.apache.geode.distributed.internal.ReplyMessage;
+import org.apache.geode.distributed.internal.ReplyProcessor21;
+import org.apache.geode.distributed.internal.ReplySender;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.Assert;
+import org.apache.geode.internal.NanoTimer;
+import org.apache.geode.internal.cache.partitioned.PartitionMessage;
+import org.apache.geode.internal.logging.log4j.LogMarker;
+import org.apache.geode.internal.serialization.DeserializationContext;
+import org.apache.geode.internal.serialization.SerializationContext;
+import org.apache.geode.logging.internal.log4j.api.LogService;
+
+public class PartitionedRegionClearMessage extends PartitionMessage {
+
+  public enum OperationType {
+    OP_LOCK_FOR_PR_CLEAR, OP_UNLOCK_FOR_PR_CLEAR, OP_PR_CLEAR,
+  }
+
+  private Object cbArg;
+
+  private OperationType op;
+
+  private EventID eventID;
+
+  private PartitionedRegion partitionedRegion;
+
+  private ArrayList bucketsCleared;
+
+  @Override
+  public EventID getEventID() {
+    return eventID;
+  }
+
+  public PartitionedRegionClearMessage() {}
+
+  PartitionedRegionClearMessage(Set recipients, PartitionedRegion region,
+      ReplyProcessor21 processor, PartitionedRegionClearMessage.OperationType operationType,
+      final RegionEventImpl event) {
+    super(recipients, region.getPRId(), processor);
+    partitionedRegion = region;
+    op = operationType;
+    cbArg = event.getRawCallbackArgument();
+    eventID = event.getEventId();
+  }
+
+  public OperationType getOp() {
+    return op;
+  }
+
+  public void send() {
+    Assert.assertTrue(getRecipients() != null, "ClearMessage NULL recipients set");
+    setTransactionDistributed(partitionedRegion.getCache().getTxManager().isDistributed());
+    partitionedRegion.getDistributionManager().putOutgoing(this);
+  }
+
+  @Override
+  protected Throwable processCheckForPR(PartitionedRegion pr,
+      DistributionManager distributionManager) {
+    if (pr != null && !pr.getDistributionAdvisor().isInitialized()) {
+      Throwable thr = new ForceReattemptException(
+          String.format("%s : could not find partitioned region with Id %s",
+              distributionManager.getDistributionManagerId(),
+              pr.getRegionIdentifier()));
+      return thr;
+    }
+    return null;
+  }
+
+  @Override
+  protected boolean operateOnPartitionedRegion(ClusterDistributionManager dm,
+      PartitionedRegion partitionedRegion,
+      long startTime) throws CacheException {
+
+    if (partitionedRegion == null) {
+      return true;
+    }
+
+    if (partitionedRegion.isDestroyed()) {
+      return true;
+    }
+
+    if (op == OperationType.OP_LOCK_FOR_PR_CLEAR) {
+      partitionedRegion.getPartitionedRegionClear().obtainClearLockLocal(getSender());
+    } else if (op == OperationType.OP_UNLOCK_FOR_PR_CLEAR) {
+      partitionedRegion.getPartitionedRegionClear().releaseClearLockLocal();
+    } else {
+      RegionEventImpl event =
+          new RegionEventImpl(partitionedRegion, Operation.REGION_CLEAR, this.cbArg, true,
+              partitionedRegion.getMyId(),
+              getEventID());
+      bucketsCleared = partitionedRegion.getPartitionedRegionClear().clearRegionLocal(event);
+    }
+    return true;
+  }
+
+  @Override
+  protected void appendFields(StringBuilder buff) {
+    super.appendFields(buff);
+    buff.append(" cbArg=").append(this.cbArg).append(" op=").append(this.op);
+  }
+
+  @Override
+  public int getDSFID() {
+    return CLEAR_PARTITIONED_REGION_MESSAGE;
+  }
+
+  @Override
+  public void fromData(DataInput in,
+      DeserializationContext context) throws IOException, ClassNotFoundException {
+    super.fromData(in, context);
+    this.cbArg = DataSerializer.readObject(in);
+    op = PartitionedRegionClearMessage.OperationType.values()[in.readByte()];
+    eventID = DataSerializer.readObject(in);
+  }
+
+  @Override
+  public void toData(DataOutput out,
+      SerializationContext context) throws IOException {
+    super.toData(out, context);
+    DataSerializer.writeObject(this.cbArg, out);
+    out.writeByte(op.ordinal());
+    DataSerializer.writeObject(eventID, out);
+  }
+
+  /**
+   * The response on which to wait for all the replies. This response ignores any exceptions
+   * received from the "far side"
+   */
+  public static class PartitionedRegionClearResponse extends ReplyProcessor21 {
+    CopyOnWriteArrayList bucketsCleared = new CopyOnWriteArrayList();
+
+    public PartitionedRegionClearResponse(InternalDistributedSystem system, Set initMembers) {
+      super(system, initMembers);
+    }
+
+    @Override
+    public void process(DistributionMessage msg) {
+      if (msg instanceof PartitionedRegionClearReplyMessage) {
+        List buckets = ((PartitionedRegionClearReplyMessage) msg).bucketsCleared;
+        if (buckets != null) {
+          bucketsCleared.addAll(buckets);
+        }
+      }
+      super.process(msg, true);
+    }
+  }
+
+  @Override
+  protected void sendReply(InternalDistributedMember member, int processorId,
+      DistributionManager distributionManager, ReplyException ex,
+      PartitionedRegion partitionedRegion, long startTime) {
+    if (partitionedRegion != null) {
+      if (startTime > 0) {
+        partitionedRegion.getPrStats().endPartitionMessagesProcessing(startTime);
+      }
+    }
+    PartitionedRegionClearMessage.PartitionedRegionClearReplyMessage
+        .send(member, processorId, getReplySender(distributionManager), op, bucketsCleared,
+            ex);
+  }
+
+  public static class PartitionedRegionClearReplyMessage extends ReplyMessage {
+
+    private ArrayList bucketsCleared;
+
+    private OperationType op;
+
+    @Override
+    public boolean getInlineProcess() {
+      return true;
+    }
+
+    /**
+     * Empty constructor to conform to DataSerializable interface
+     */
+    public PartitionedRegionClearReplyMessage() {}
+
+    private PartitionedRegionClearReplyMessage(int processorId, OperationType op,
+        ArrayList bucketsCleared, ReplyException ex) {
+      super();
+      this.bucketsCleared = bucketsCleared;
+      this.op = op;
+      setProcessorId(processorId);
+      setException(ex);
+    }
+
+    /** Send an ack */
+    public static void send(InternalDistributedMember recipient, int processorId, ReplySender dm,
+        OperationType op, ArrayList bucketsCleared, ReplyException ex) {
+
+      Assert.assertTrue(recipient != null, "partitionedRegionClearReplyMessage NULL reply message");
+
+      PartitionedRegionClearMessage.PartitionedRegionClearReplyMessage m =
+          new PartitionedRegionClearMessage.PartitionedRegionClearReplyMessage(processorId, op,
+              bucketsCleared, ex);
+
+      m.setRecipient(recipient);
+      dm.putOutgoing(m);
+    }
+
+    /**
+     * Processes this message. This method is invoked by the receiver of the message.
+     *
+     * @param dm the distribution manager that is processing the message.
+     */
+    @Override
+    public void process(final DistributionManager dm, final ReplyProcessor21 rp) {
+      final long startTime = getTimestamp();
+
+      if (rp == null) {
+        if (LogService.getLogger().isTraceEnabled(LogMarker.DM_VERBOSE)) {
+          LogService.getLogger().trace(LogMarker.DM_VERBOSE, "{}: processor not found", this);
+        }
+        return;
+      }
+
+      rp.process(this);
+
+      dm.getStats().incReplyMessageTime(NanoTimer.getTime() - startTime);
+    }
+
+    @Override
+    public int getDSFID() {
+      return CLEAR_PARTITIONED_REGION_REPLY_MESSAGE;
+    }
+
+    @Override
+    public void fromData(DataInput in,
+        DeserializationContext context) throws IOException, ClassNotFoundException {
+      super.fromData(in, context);
+      op = PartitionedRegionClearMessage.OperationType.values()[in.readByte()];
+      bucketsCleared = DataSerializer.readArrayList(in);
+    }
+
+    @Override
+    public void toData(DataOutput out,
+        SerializationContext context) throws IOException {
+      super.toData(out, context);
+      out.writeByte(op.ordinal());
+      DataSerializer.writeArrayList(bucketsCleared, out);
+    }
+
+    @Override
+    public String toString() {
+      StringBuffer sb = new StringBuffer();
+      sb.append("PartitionedRegionClearReplyMessage ")
+          .append("processorId=").append(this.processorId)
+          .append(" sender=").append(sender)
+          .append(" bucketsCleared ").append(this.bucketsCleared)
+          .append(" exception=").append(getException());
+      return sb.toString();
+    }
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java
index 23a7487..578ed3e 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java
@@ -980,6 +980,14 @@ public class PartitionedRegionDataStore implements HasCachePerfStats {
     }
   }
 
+  protected void lockBucketCreationForRegionClear() {
+    bucketCreationLock.writeLock().lock();
+  }
+
+  protected void unlockBucketCreationForRegionClear() {
+    bucketCreationLock.writeLock().unlock();
+  }
+
   /**
    * Gets the total amount of memory in bytes allocated for all values for this PR in this VM. This
    * is the current memory (MB) watermark for data in this PR.
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/RegionAdvisor.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/RegionAdvisor.java
index 5d2ff24..13ad666 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/RegionAdvisor.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/RegionAdvisor.java
@@ -851,10 +851,21 @@ public class RegionAdvisor extends CacheDistributionAdvisor {
         && prof.filterProfile.hasInterest();
   };
 
+  @Immutable
+  private static final Filter prServerWithCqFilter = profile -> {
+    CacheProfile prof = (CacheProfile) profile;
+    return prof.isPartitioned && prof.hasCacheServer && prof.filterProfile != null
+        && prof.filterProfile.hasCQs();
+  };
+
   public boolean hasPRServerWithInterest() {
     return satisfiesFilter(prServerWithInterestFilter);
   }
 
+  public boolean hasPRServerWithCQs() {
+    return satisfiesFilter(prServerWithCqFilter);
+  }
+
   /**
    * return the set of all members who must receive operation notifications
    *
diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index eeee864..d69c6b5 100644
--- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -79,6 +79,7 @@ org/apache/geode/cache/NoSubscriptionServersAvailableException,true,848408601915
 org/apache/geode/cache/Operation,true,-7521751729852504238,ordinal:byte
 org/apache/geode/cache/OperationAbortedException,true,-8293166225026556949
 org/apache/geode/cache/PartitionedRegionDistributionException,true,-3004093739855972548
+org/apache/geode/cache/PartitionedRegionPartialClearException,false
 org/apache/geode/cache/PartitionedRegionStorageException,true,5905463619475329732
 org/apache/geode/cache/RegionAccessException,true,3142958723089038406
 org/apache/geode/cache/RegionDestroyedException,true,319804842308010754,regionFullPath:java/lang/String
@@ -303,6 +304,7 @@ org/apache/geode/internal/cache/PRContainsValueFunction,false
 org/apache/geode/internal/cache/PRHARedundancyProvider$ArrayListWithClearState,true,1,wasCleared:boolean
 org/apache/geode/internal/cache/PartitionedRegion$PRIdMap,true,3667357372967498179,cleared:boolean
 org/apache/geode/internal/cache/PartitionedRegion$SizeEntry,false,isPrimary:boolean,size:int
+org/apache/geode/internal/cache/PartitionedRegionClearMessage$OperationType,false
 org/apache/geode/internal/cache/PartitionedRegionDataStore$CreateBucketResult,false,nowExists:boolean
 org/apache/geode/internal/cache/PartitionedRegionException,true,5113786059279106007
 org/apache/geode/internal/cache/PartitionedRegionQueryEvaluator$MemberResultsList,false,isLastChunkReceived:boolean
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java
index c7cf5a6..d3397eb 100755
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/BucketRegionJUnitTest.java
@@ -51,7 +51,9 @@ public class BucketRegionJUnitTest extends DistributedRegionJUnitTest {
     when(ba.getPrimaryMoveReadLock()).thenReturn(primaryMoveReadLock);
     when(ba.getProxyBucketRegion()).thenReturn(mock(ProxyBucketRegion.class));
     when(ba.isPrimary()).thenReturn(true);
-
+    PartitionedRegionClear clearPR = mock(PartitionedRegionClear.class);
+    when(clearPR.isLockedForListenerAndClientNotification()).thenReturn(true);
+    when(pr.getPartitionedRegionClear()).thenReturn(clearPR);
     ira.setPartitionedRegion(pr).setPartitionedRegionBucketRedundancy(1).setBucketAdvisor(ba);
   }
 
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java
index 898c4f7..e02ba2c 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionTest.java
@@ -58,7 +58,6 @@ import org.mockito.junit.MockitoRule;
 import org.apache.geode.CancelCriterion;
 import org.apache.geode.Statistics;
 import org.apache.geode.cache.AttributesFactory;
-import org.apache.geode.cache.CacheClosedException;
 import org.apache.geode.cache.CacheLoader;
 import org.apache.geode.cache.CacheWriter;
 import org.apache.geode.cache.Operation;
@@ -221,22 +220,6 @@ public class PartitionedRegionTest {
     spyPartitionedRegion.clear();
   }
 
-  @Test(expected = CacheClosedException.class)
-  public void clearShouldThrowCacheClosedExceptionIfShutdownAll() {
-    PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
-    RegionEventImpl regionEvent =
-        new RegionEventImpl(spyPartitionedRegion, Operation.REGION_CLEAR, null, false,
-            spyPartitionedRegion.getMyId(), true);
-    when(cache.isCacheAtShutdownAll()).thenReturn(true);
-    when(cache.getCacheClosedException("Cache is shutting down"))
-        .thenReturn(new CacheClosedException("Cache is shutting down"));
-    DistributedLockService lockService = mock(DistributedLockService.class);
-    when(spyPartitionedRegion.getPartitionedRegionLockService()).thenReturn(lockService);
-    String lockName = "_clearOperation" + spyPartitionedRegion.getFullPath().replace('/', '_');
-    when(lockService.lock(lockName, -1, -1)).thenReturn(true);
-    spyPartitionedRegion.basicClear(regionEvent, true);
-  }
-
   @Test
   public void createClearPRMessagesShouldCreateMessagePerBucket() {
     PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
@@ -249,28 +232,6 @@ public class PartitionedRegionTest {
     assertThat(msgs.size()).isEqualTo(3);
   }
 
-  @Test
-  public void sendEachMessagePerBucket() {
-    PartitionedRegion spyPartitionedRegion = spy(partitionedRegion);
-    RegionEventImpl regionEvent =
-        new RegionEventImpl(spyPartitionedRegion, Operation.REGION_CLEAR, null, false,
-            spyPartitionedRegion.getMyId(), true);
-    when(cache.isCacheAtShutdownAll()).thenReturn(false);
-    DistributedLockService lockService = mock(DistributedLockService.class);
-    when(spyPartitionedRegion.getPartitionedRegionLockService()).thenReturn(lockService);
-    when(spyPartitionedRegion.getTotalNumberOfBuckets()).thenReturn(3);
-    String lockName = "_clearOperation" + spyPartitionedRegion.getFullPath().replace('/', '_');
-    when(lockService.lock(lockName, -1, -1)).thenReturn(true);
-    when(spyPartitionedRegion.hasListener()).thenReturn(true);
-    doNothing().when(spyPartitionedRegion).dispatchListenerEvent(any(), any());
-    doNothing().when(spyPartitionedRegion).notifyBridgeClients(eq(regionEvent));
-    doNothing().when(spyPartitionedRegion).checkReadiness();
-    doNothing().when(lockService).unlock(lockName);
-    spyPartitionedRegion.basicClear(regionEvent, true);
-    verify(spyPartitionedRegion, times(3)).sendClearMsgByBucket(any(), any());
-    verify(spyPartitionedRegion, times(1)).dispatchListenerEvent(any(), any());
-    verify(spyPartitionedRegion, times(1)).notifyBridgeClients(eq(regionEvent));
-  }
 
   @Test
   public void getBucketNodeForReadOrWriteReturnsPrimaryNodeForRegisterInterest() {
diff --git a/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java b/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
index 7eabedb..22c78e3 100644
--- a/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
+++ b/geode-serialization/src/main/java/org/apache/geode/internal/serialization/DataSerializableFixedID.java
@@ -56,6 +56,8 @@ public interface DataSerializableFixedID extends SerializationVersions, BasicSer
 
   // NOTE, codes < -65536 will take 4 bytes to serialize
   // NOTE, codes < -128 will take 2 bytes to serialize
+  short CLEAR_PARTITIONED_REGION_REPLY_MESSAGE = -166;
+  short CLEAR_PARTITIONED_REGION_MESSAGE = -165;
 
   short PR_CLEAR_REPLY_MESSAGE = -164;
   short PR_CLEAR_MESSAGE = -163;


[geode] 10/11: GEODE-7667: Fixing test to include PR clear help text.

Posted by nn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git

commit b56bbd70db07d953e963fbb2ecf8b6c1c0e32337
Author: Nabarun Nag <na...@cs.wisc.edu>
AuthorDate: Mon May 11 16:52:50 2020 -0700

    GEODE-7667: Fixing test to include PR clear help text.
---
 .../internal/cli/GfshParserAutoCompletionIntegrationTest.java           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/geode-gfsh/src/integrationTest/java/org/apache/geode/management/internal/cli/GfshParserAutoCompletionIntegrationTest.java b/geode-gfsh/src/integrationTest/java/org/apache/geode/management/internal/cli/GfshParserAutoCompletionIntegrationTest.java
index 4c29427..3bc6a03 100644
--- a/geode-gfsh/src/integrationTest/java/org/apache/geode/management/internal/cli/GfshParserAutoCompletionIntegrationTest.java
+++ b/geode-gfsh/src/integrationTest/java/org/apache/geode/management/internal/cli/GfshParserAutoCompletionIntegrationTest.java
@@ -381,7 +381,7 @@ public class GfshParserAutoCompletionIntegrationTest {
     String hintArgument = "data";
     String hintsProvided = gfshParserRule.getCommandManager().obtainHint(hintArgument);
     String[] hintsProvidedArray = hintsProvided.split(lineSeparator());
-    assertThat(hintsProvidedArray.length).isEqualTo(17);
+    assertThat(hintsProvidedArray.length).isEqualTo(18);
     assertThat(hintsProvidedArray[0])
         .isEqualTo("User data as stored in regions of the Geode distributed system.");
   }