private void notifyPossibleDuplicate(int reason, List<?> events) {
    Map<String, Map<Integer, List<Object>>> regionToDispatchedKeysMap = new HashMap<>();
    boolean pgwsender = (getSender().isParallel()
        && !(getDispatcher() instanceof GatewaySenderEventCallbackDispatcher));

    for (Object o : events) {
      if (o instanceof GatewaySenderEventImpl) {
        GatewaySenderEventImpl ge = (GatewaySenderEventImpl) o;
        if (!ge.getPossibleDuplicate()) {
          if (pgwsender) {
            addDuplicateEvent(regionToDispatchedKeysMap, ge);
          }
          ge.setPossibleDuplicate(true);
        }
      }
    }

    if (!pgwsender) {
      return;
    }

    PartitionedRegion queueRegion;
    if (queue instanceof ConcurrentParallelGatewaySenderQueue) {
      queueRegion =
          (PartitionedRegion) ((ConcurrentParallelGatewaySenderQueue) queue).getRegion();
    } else {
      queueRegion =
          (PartitionedRegion) ((ParallelGatewaySenderQueue) queue).getRegion();
    }

    if (queueRegion == null || queueRegion.getRegionAdvisor() == null
        || queueRegion.getDataStore() == null) {
      return;
    }

    if (reason == STOPPED_GATEWAY_SENDER) {
      final Set<Integer> buckets = queueRegion.getDataStore().getAllLocalPrimaryBucketIds();
      if (regionToDispatchedKeysMap.isEmpty()) {
        if (queueRegion.isSentGatewaySenderStoppedMessage()) {
          return;
        }
        Map<Integer, List<Object>> bucketIdToDispatchedKeys = new HashMap<>();
        for (Integer bId : buckets) {
          bucketIdToDispatchedKeys.put(bId, Collections.emptyList());
        }
        regionToDispatchedKeysMap.put(queueRegion.getFullPath(), bucketIdToDispatchedKeys);

      } else {
        Map<Integer, List<Object>> bucketIdToDispatchedKeys =
            regionToDispatchedKeysMap.get(queueRegion.getFullPath());
        if (bucketIdToDispatchedKeys == null) {
          return;
        }
        for (Integer bId : buckets) {
          bucketIdToDispatchedKeys.putIfAbsent(bId, Collections.emptyList());
        }
      }
    }

    if (regionToDispatchedKeysMap.size() > 0) {
      Set<InternalDistributedMember> recipients =
          getAllRecipients(sender.getCache(), regionToDispatchedKeysMap);

      if (recipients.isEmpty()) {
        return;
      }

      if (reason == STOPPED_GATEWAY_SENDER) {
        if (!queueRegion.isSentGatewaySenderStoppedMessage()) {
          queueRegion.setSentGatewaySenderStoppedMessage(true);
        }
      }

      InternalDistributedSystem ids = sender.getCache().getInternalDistributedSystem();
      DistributionManager dm = ids.getDistributionManager();
      dm.retainMembersWithSameOrNewerVersion(recipients, KnownVersion.GEODE_1_15_0);

      if (!recipients.isEmpty()) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "notifyPossibleDuplicate send ParallelQueueSetPossibleDuplicateMessage recipients {}.",
              recipients);
        }

        ParallelQueueSetPossibleDuplicateMessage pqspdm =
            new ParallelQueueSetPossibleDuplicateMessage(reason, regionToDispatchedKeysMap);
        pqspdm.setRecipients(recipients);
        dm.putOutgoing(pqspdm);
      }
    }

  }
Logs a batch of events.

@param events The batch of events to log
geode-core/src/main/java/org/apache/geode/internal/cache/wan/AbstractGatewaySenderEventProcessor.java