All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.geode.internal.cache.wan.GatewaySenderAdvisor Maven / Gradle / Ivy

Go to download

Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing

There is a newer version: 1.15.1
Show newest version
/*
 * 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.wan;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.logging.log4j.Logger;

import org.apache.geode.CancelException;
import org.apache.geode.DataSerializer;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.asyncqueue.AsyncEventListener;
import org.apache.geode.cache.wan.GatewaySender.OrderPolicy;
import org.apache.geode.cache.wan.GatewayTransportFilter;
import org.apache.geode.distributed.DistributedLockService;
import org.apache.geode.distributed.internal.DistributionAdvisee;
import org.apache.geode.distributed.internal.DistributionAdvisor;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.ServerLocation;
import org.apache.geode.distributed.internal.locks.DLockService;
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.Version;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.UpdateAttributesProcessor;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.logging.LoggingThreadGroup;
import org.apache.geode.internal.logging.log4j.LocalizedMessage;

public class GatewaySenderAdvisor extends DistributionAdvisor {
  private static final Logger logger = LogService.getLogger();

  private DistributedLockService lockService;

  private volatile boolean isPrimary;

  private final Object primaryLock = new Object();

  private final String lockToken;

  private Thread lockObtainingThread;

  private final ThreadGroup threadGroup =
      LoggingThreadGroup.createThreadGroup("GatewaySenderAdvisor Threads");

  private AbstractGatewaySender sender;

  private GatewaySenderAdvisor(DistributionAdvisee sender) {
    super(sender);
    this.sender = (AbstractGatewaySender) sender;
    this.lockToken = getDLockServiceName() + "-token";
  }

  public static GatewaySenderAdvisor createGatewaySenderAdvisor(DistributionAdvisee sender) {
    GatewaySenderAdvisor advisor = new GatewaySenderAdvisor(sender);
    advisor.initialize();
    return advisor;
  }

  public String getDLockServiceName() {
    return getClass().getName() + "_" + this.sender.getId();
  }

  public Thread getLockObtainingThread() {
    return this.lockObtainingThread;
  }

  /** Instantiate new Sender profile for this member */
  @Override
  protected Profile instantiateProfile(InternalDistributedMember memberId, int version) {
    return new GatewaySenderProfile(memberId, version);
  }

  /**
   * The profile will be created when the sender is added to the cache. here we are not starting the
   * sender. so we should not release or acquire any lock for the sender to become primary based on
   * creation only.
   */
  @Override
  public void profileCreated(Profile profile) {
    if (profile instanceof GatewaySenderProfile) {
      GatewaySenderProfile sp = (GatewaySenderProfile) profile;
      checkCompatibility(sp);
    }
  }

  private void checkCompatibility(GatewaySenderProfile sp) {
    if (sp.remoteDSId != sender.getRemoteDSId()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_REMOTE_DS_ID_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_2_REMOTE_DS_ID
              .toString(new Object[] {sp.Id, sp.remoteDSId, sender.remoteDSId}));
    }
    if (sp.isParallel && !sender.isParallel()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_AS_PARALLEL_GATEWAY_SENDER_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_AS_SERIAL_GATEWAY_SENDER
              .toString(new Object[] {sp.Id}));
    }
    if (!sp.isParallel && sender.isParallel()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_AS_SERIAL_GATEWAY_SENDER_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_AS_PARALLEL_GATEWAY_SENDER
              .toString(new Object[] {sp.Id}));
    }

    if (sp.isBatchConflationEnabled != sender.isBatchConflationEnabled()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_IS_BACTH_CONFLATION_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_IS_BATCH_CONFLATION_2
              .toString(new Object[] {sp.Id, sp.isBatchConflationEnabled,
                  sender.isBatchConflationEnabled()}));
    }
    if (sp.isPersistenceEnabled != sender.isPersistenceEnabled()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_IS_PERSISTENT_ENABLED_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_IS_PERSISTENT_ENABLED_2
              .toString(
                  new Object[] {sp.Id, sp.isPersistenceEnabled, sender.isPersistenceEnabled()}));
    }
    if (sp.alertThreshold != sender.getAlertThreshold()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_ALERT_THRESHOLD_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_ALERT_THRESHOLD_2
              .toString(new Object[] {sp.Id, sp.alertThreshold, sender.getAlertThreshold()}));
    }
    if (!sender.isParallel()) {
      if (sp.manualStart != sender.isManualStart()) {
        throw new IllegalStateException(
            LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_MANUAL_START_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_MANUAL_START_2
                .toString(new Object[] {sp.Id, sp.manualStart, sender.isManualStart()}));
      }
    }
    /*
     * if(sp.dispatcherThreads != sender.getDispatcherThreads()) { throw new IllegalStateException(
     * LocalizedStrings.
     * GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_DISPATCHER_THREAD_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_DISPATCHER_THREAD_2
     * .toString(new Object[] { sp.Id, sp.dispatcherThreads, sender.getDispatcherThreads() })); }
     */

    if (!sp.isParallel) {
      if (sp.orderPolicy != sender.getOrderPolicy()) {
        throw new IllegalStateException(
            LocalizedStrings.GatewaySenderAdvisor_CANNOT_CREATE_GATEWAYSENDER_0_WITH_ORDER_POLICY_1_BECAUSE_ANOTHER_CACHE_HAS_THE_SAME_SENDER_WITH_ORDER_POLICY_2
                .toString(new Object[] {sp.Id, sp.orderPolicy, sender.getOrderPolicy()}));
      }
    }

    List senderEventFilterClassNames = new ArrayList();
    for (org.apache.geode.cache.wan.GatewayEventFilter filter : sender.getGatewayEventFilters()) {
      senderEventFilterClassNames.add(filter.getClass().getName());
    }
    if (sp.eventFiltersClassNames.size() != senderEventFilterClassNames.size()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_GATEWAY_EVENT_FILTERS_MISMATCH.toString(
              new Object[] {sp.Id, sp.eventFiltersClassNames, senderEventFilterClassNames}));
    } else {
      for (String filterName : senderEventFilterClassNames) {
        if (!sp.eventFiltersClassNames.contains(filterName)) {
          throw new IllegalStateException(
              LocalizedStrings.GatewaySenderAdvisor_GATEWAY_EVENT_FILTERS_MISMATCH.toString(
                  new Object[] {sp.Id, sp.eventFiltersClassNames, senderEventFilterClassNames}));
        }
      }
    }

    Set senderTransportFilterClassNames = new LinkedHashSet();
    for (GatewayTransportFilter filter : sender.getGatewayTransportFilters()) {
      senderTransportFilterClassNames.add(filter.getClass().getName());
    }
    if (sp.transFiltersClassNames.size() != senderTransportFilterClassNames.size()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_GATEWAY_TRANSPORT_FILTERS_MISMATCH.toString(
              new Object[] {sp.Id, sp.transFiltersClassNames, senderTransportFilterClassNames}));
    } else {
      Iterator i1 = sp.transFiltersClassNames.iterator();
      Iterator i2 = senderTransportFilterClassNames.iterator();
      while (i1.hasNext() && i2.hasNext()) {
        if (!i1.next().equals(i2.next())) {
          throw new IllegalStateException(
              LocalizedStrings.GatewaySenderAdvisor_GATEWAY_TRANSPORT_FILTERS_MISMATCH
                  .toString(new Object[] {sp.Id, sp.transFiltersClassNames,
                      senderTransportFilterClassNames}));
        }
      }
    }
    List senderEventListenerClassNames = new ArrayList();
    for (AsyncEventListener listener : sender.getAsyncEventListeners()) {
      senderEventListenerClassNames.add(listener.getClass().getName());
    }
    if (sp.senderEventListenerClassNames.size() != senderEventListenerClassNames.size()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_GATEWAY_SENDER_LISTENER_MISMATCH
              .toString(new Object[] {sp.Id, sp.senderEventListenerClassNames,
                  senderEventListenerClassNames}));
    } else {
      for (String listenerName : senderEventListenerClassNames) {
        if (!sp.senderEventListenerClassNames.contains(listenerName)) {
          throw new IllegalStateException(
              LocalizedStrings.GatewaySenderAdvisor_GATEWAY_SENDER_LISTENER_MISMATCH
                  .toString(new Object[] {sp.Id, sp.senderEventListenerClassNames,
                      senderEventListenerClassNames}));
        }
      }
    }
    if (sp.isDiskSynchronous != sender.isDiskSynchronous()) {
      throw new IllegalStateException(
          LocalizedStrings.GatewaySenderAdvisor_GATEWAY_SENDER_IS_DISK_SYNCHRONOUS_MISMATCH
              .toString(new Object[] {sp.Id, sp.isDiskSynchronous, sender.isDiskSynchronous()}));
    }
  }

  /**
   * If there is change in sender which having policy as primary. 1. If that sender is stopped then
   * if there are no other primary senders then this sender should volunteer for primary. 2. If this
   * sender is primary and its policy is secondary then this sender should release the lock so that
   * other primary sender which s waiting on lock will get the lock.
   * 
   */

  @Override
  public void profileUpdated(Profile profile) {
    if (profile instanceof GatewaySenderProfile) {
      GatewaySenderProfile sp = (GatewaySenderProfile) profile;
      if (!sp.isParallel) { // SerialGatewaySender
        if (!sp.isRunning) {
          if (advisePrimaryGatewaySender() != null) {
            return;
          }
          // IF this sender is not primary
          if (!this.sender.isPrimary()) {
            if (!adviseEldestGatewaySender()) {// AND this is not the eldest
                                               // sender
              if (logger.isDebugEnabled()) {
                logger.debug(
                    "Sender {} is not the eldest in the system. Giving preference to eldest sender to become primary...",
                    this.sender);
              }
              return;
            }
            launchLockObtainingVolunteerThread();
          }
        } else {
          if (sp.serverLocation != null) {
            this.sender.setServerLocation(sp.serverLocation);
          }
        }
      }
    }
  }

  /**
   * When the sender profile is removed, then check for the primary members if they are not
   * available then this secondary sender should volunteer for primary
   */
  @Override
  protected void profileRemoved(Profile profile) {
    if (profile instanceof GatewaySenderProfile) {
      GatewaySenderProfile sp = (GatewaySenderProfile) profile;
      if (!sp.isParallel) {// SerialGatewaySender
        // if there is a primary sender, then don't volunteer for primary
        if (advisePrimaryGatewaySender() != null) {
          return;
        }
        if (!this.sender.isPrimary()) {// IF this sender is not primary
          if (!adviseEldestGatewaySender()) {// AND this is not the eldest sender
            if (logger.isDebugEnabled()) {
              logger.debug(
                  "Sender {} is not the eldest in the system. Giving preference to eldest sender to become primary...",
                  this.sender);
            }
            return;
          }
          launchLockObtainingVolunteerThread();
        }
      }
    }
  }

  public boolean isPrimary() {
    return sender.isParallel() || this.isPrimary;
  }

  public void initDLockService() {
    InternalDistributedSystem ds =
        ((GemFireCacheImpl) this.sender.getCache()).getDistributedSystem();
    String dlsName = getDLockServiceName();
    this.lockService = DistributedLockService.getServiceNamed(dlsName);
    if (this.lockService == null) {
      this.lockService = DLockService.create(dlsName, ds, true, true, true);
    }
    Assert.assertTrue(this.lockService != null);
    if (logger.isDebugEnabled()) {
      logger.debug("{}: Obtained DistributedLockService: {}", this, this.lockService);
    }
  }

  public boolean volunteerForPrimary() {
    if (logger.isDebugEnabled()) {
      logger.debug("Sender : {} is volunteering for Primary ", this.sender.getId());
    }

    if (advisePrimaryGatewaySender() == null) {
      if (!adviseEldestGatewaySender()) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Sender {} is not the eldest in the system. Giving preference to eldest sender to become primary...",
              this.sender);
        }
        return false;
      }
      if (logger.isDebugEnabled()) {
        logger.debug("Sender : {} no Primary available. So going to acquire distributed lock",
            this.sender);
      }
      this.lockService.lock(this.lockToken, 10000, -1);
      return this.lockService.isHeldByCurrentThread(this.lockToken);
    }
    return false;
  }

  /**
   * Find out if this sender is the eldest in the DS. Returns true if: 1. No other sender is running
   * 2. At least one sender is running in the system apart from this sender AND this sender's start
   * time is lesser of all (i.e. this sender is oldest)
   * 
   * @return boolean true if this eldest sender; false otherwise
   */
  private boolean adviseEldestGatewaySender() {
    Profile[] snapshot = this.profiles;

    // sender with minimum startTime is eldest. Find out the minimum start time
    // of remote senders.
    TreeSet senderStartTimes = new TreeSet();
    for (Profile profile : snapshot) {
      GatewaySenderProfile sp = (GatewaySenderProfile) profile;
      if (!sp.isParallel && sp.isRunning) {
        senderStartTimes.add(sp.startTime);
      }
    }

    // if none of the remote senders is running, then this sender should
    // volunteer for primary
    // if there are remote senders running and this sender is not running then
    // it should give up
    // and allow existing running senders to volunteer
    return (senderStartTimes.isEmpty())
        || (this.sender.isRunning() && (this.sender.startTime <= senderStartTimes.first()));
  }

  private InternalDistributedMember adviseEldestGatewaySenderNode() {
    Profile[] snapshot = this.profiles;

    // sender with minimum startTime is eldest. Find out the minimum start time
    // of remote senders.
    InternalDistributedMember node = null;
    GatewaySenderProfile eldestProfile = null;
    for (Profile profile : snapshot) {
      GatewaySenderProfile sp = (GatewaySenderProfile) profile;
      if (!sp.isParallel && sp.isRunning) {
        if (eldestProfile == null) {
          eldestProfile = sp;
        }
        if (sp.startTime < eldestProfile.startTime) {
          eldestProfile = sp;
        }
      }
    }

    if (eldestProfile != null) {
      node = eldestProfile.getDistributedMember();
    }
    return node;
  }

  public void makePrimary() {
    logger.info(LocalizedMessage
        .create(LocalizedStrings.SerialGatewaySenderImpl_0__STARTING_AS_PRIMARY, this.sender));
    AbstractGatewaySenderEventProcessor eventProcessor = this.sender.getEventProcessor();
    if (eventProcessor != null) {
      eventProcessor.removeCacheListener();
    }

    logger.info(LocalizedMessage.create(
        LocalizedStrings.SerialGatewaySenderImpl_0__BECOMING_PRIMARY_GATEWAYSENDER, this.sender));
    notifyAndBecomePrimary();
    new UpdateAttributesProcessor(this.sender).distribute(false);
  }

  public void notifyAndBecomePrimary() {
    synchronized (this.primaryLock) {
      setIsPrimary(true);
      notifyPrimaryLock();
    }
  }

  public void notifyPrimaryLock() {
    synchronized (this.primaryLock) {
      this.primaryLock.notifyAll();
    }
  }

  public void makeSecondary() {
    if (logger.isDebugEnabled()) {
      logger.debug("{}: Did not obtain the lock on {}. Starting as secondary gateway sender.",
          this.sender, this.lockToken);
    }

    // Set primary flag to false
    logger.info(LocalizedMessage.create(
        LocalizedStrings.SerialGatewaySenderImpl_0__STARTING_AS_SECONDARY_BECAUSE_PRIMARY_GATEWAY_SENDER_IS_AVAIALABLE_ON_MEMBER_2,
        new Object[] {this.sender.getId(), advisePrimaryGatewaySender()}));
    this.isPrimary = false;
    new UpdateAttributesProcessor(this.sender).distribute(false);
  }

  public void launchLockObtainingVolunteerThread() {
    this.lockObtainingThread = new Thread(threadGroup, new Runnable() {
      @SuppressWarnings("synthetic-access")
      public void run() {
        GatewaySenderAdvisor.this.sender.getLifeCycleLock().readLock().lock();
        try {
          // Attempt to obtain the lock
          if (!(GatewaySenderAdvisor.this.sender.isRunning())) {
            return;
          }
          if (logger.isDebugEnabled()) {
            logger.debug("{}: Obtaining the lock on {}", this, GatewaySenderAdvisor.this.lockToken);
          }

          if (volunteerForPrimary()) {
            if (logger.isDebugEnabled()) {
              logger.debug("{}: Obtained the lock on {}", this,
                  GatewaySenderAdvisor.this.lockToken);
            }
            logger.info(LocalizedMessage.create(
                LocalizedStrings.GatewaySender_0_IS_BECOMING_PRIMARY_GATEWAY_Sender,
                GatewaySenderAdvisor.this));

            // As soon as the lock is obtained, set primary
            GatewaySenderAdvisor.this.makePrimary();
          }
        } catch (CancelException e) {
          // no action necessary
        } catch (Exception e) {
          if (!sender.getStopper().isCancelInProgress()) {
            logger.fatal(LocalizedMessage.create(
                LocalizedStrings.GatewaySenderAdvisor_0_THE_THREAD_TO_OBTAIN_THE_FAILOVER_LOCK_WAS_INTERRUPTED__THIS_GATEWAY_SENDER_WILL_NEVER_BECOME_THE_PRIMARY,
                GatewaySenderAdvisor.this), e);
          }
        } finally {
          GatewaySenderAdvisor.this.sender.getLifeCycleLock().readLock().unlock();
        }
      }
    }, "Gateway Sender Primary Lock Acquisition Thread Volunteer");

    this.lockObtainingThread.setDaemon(true);
    this.lockObtainingThread.start();
  }

  public void waitToBecomePrimary(AbstractGatewaySenderEventProcessor callingProcessor)
      throws InterruptedException {
    if (isPrimary()) {
      return;
    }
    synchronized (this.primaryLock) {
      logger.info(LocalizedMessage.create(
          LocalizedStrings.GatewayImpl_0__WAITING_TO_BECOME_PRIMARY_GATEWAY, this.sender.getId()));
      while (!isPrimary()) {
        this.primaryLock.wait(1000);
        if (sender.getEventProcessor() != null && callingProcessor.isStopped()) {
          logger.info("The event processor is stopped, not to wait for being primary any more.");
          return;
        }
      }
    }
  }

  /**
   * Profile information for a remote counterpart.
   */
  public static final class GatewaySenderProfile extends DistributionAdvisor.Profile {
    public String Id;

    public long startTime;

    public int remoteDSId;

    /**
     * I need this boolean to make sure the sender which is volunteer for primary is running. not
     * running sender should not become primary.
     */
    public boolean isRunning;

    public boolean isPrimary;

    public boolean isParallel;

    public boolean isBatchConflationEnabled;

    public boolean isPersistenceEnabled;

    public int alertThreshold;

    public boolean manualStart;

    public ArrayList eventFiltersClassNames = new ArrayList();

    public ArrayList transFiltersClassNames = new ArrayList();

    public ArrayList senderEventListenerClassNames = new ArrayList();

    public boolean isDiskSynchronous;

    public int dispatcherThreads;

    public OrderPolicy orderPolicy;

    public ServerLocation serverLocation;

    public GatewaySenderProfile(InternalDistributedMember memberId, int version) {
      super(memberId, version);
    }

    public GatewaySenderProfile() {}

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.Id = DataSerializer.readString(in);
      this.startTime = in.readLong();
      this.remoteDSId = in.readInt();
      this.isRunning = in.readBoolean();
      this.isPrimary = in.readBoolean();
      this.isParallel = in.readBoolean();
      this.isBatchConflationEnabled = in.readBoolean();
      this.isPersistenceEnabled = in.readBoolean();
      this.alertThreshold = in.readInt();
      this.manualStart = in.readBoolean();
      this.eventFiltersClassNames = DataSerializer.readArrayList(in);
      this.transFiltersClassNames = DataSerializer.readArrayList(in);
      this.senderEventListenerClassNames = DataSerializer.readArrayList(in);
      this.isDiskSynchronous = in.readBoolean();
      this.dispatcherThreads = in.readInt();
      if (InternalDataSerializer.getVersionForDataStream(in).compareTo(Version.CURRENT) < 0) {
        org.apache.geode.cache.util.Gateway.OrderPolicy oldOrderPolicy =
            DataSerializer.readObject(in);
        if (oldOrderPolicy != null) {
          if (oldOrderPolicy.name().equals(OrderPolicy.KEY.name())) {
            this.orderPolicy = OrderPolicy.KEY;
          } else if (oldOrderPolicy.name().equals(OrderPolicy.THREAD.name())) {
            this.orderPolicy = OrderPolicy.THREAD;
          } else {
            this.orderPolicy = OrderPolicy.PARTITION;
          }
        } else {
          this.orderPolicy = null;
        }
      } else {
        this.orderPolicy = DataSerializer.readObject(in);
      }
      boolean serverLocationFound = DataSerializer.readPrimitiveBoolean(in);
      if (serverLocationFound) {
        this.serverLocation = new ServerLocation();
        InternalDataSerializer.invokeFromData(this.serverLocation, in);
      }
    }

    @Override
    public void toData(DataOutput out) throws IOException {
      super.toData(out);
      DataSerializer.writeString(Id, out);
      out.writeLong(startTime);
      out.writeInt(remoteDSId);
      out.writeBoolean(isRunning);
      out.writeBoolean(isPrimary);
      out.writeBoolean(isParallel);
      out.writeBoolean(isBatchConflationEnabled);
      out.writeBoolean(isPersistenceEnabled);
      out.writeInt(alertThreshold);
      out.writeBoolean(manualStart);
      DataSerializer.writeArrayList(eventFiltersClassNames, out);
      DataSerializer.writeArrayList(transFiltersClassNames, out);
      DataSerializer.writeArrayList(senderEventListenerClassNames, out);
      out.writeBoolean(isDiskSynchronous);
      out.writeInt(dispatcherThreads);
      if (InternalDataSerializer.getVersionForDataStream(out).compareTo(Version.CURRENT) < 0
          && this.orderPolicy != null) {
        String orderPolicyName = this.orderPolicy.name();
        if (orderPolicyName.equals(org.apache.geode.cache.util.Gateway.OrderPolicy.KEY.name())) {
          DataSerializer.writeObject(org.apache.geode.cache.util.Gateway.OrderPolicy.KEY, out);
        } else if (orderPolicyName
            .equals(org.apache.geode.cache.util.Gateway.OrderPolicy.THREAD.name())) {
          DataSerializer.writeObject(org.apache.geode.cache.util.Gateway.OrderPolicy.THREAD, out);
        } else {
          DataSerializer.writeObject(org.apache.geode.cache.util.Gateway.OrderPolicy.PARTITION,
              out);
        }
      } else {
        DataSerializer.writeObject(orderPolicy, out);
      }
      boolean serverLocationFound = (this.serverLocation != null);
      DataSerializer.writePrimitiveBoolean(serverLocationFound, out);
      if (serverLocationFound) {
        InternalDataSerializer.invokeToData(serverLocation, out);
      }
    }

    public void fromDataPre_GFE_8_0_0_0(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.Id = DataSerializer.readString(in);
      this.startTime = in.readLong();
      this.remoteDSId = in.readInt();
      this.isRunning = in.readBoolean();
      this.isPrimary = in.readBoolean();
      this.isParallel = in.readBoolean();
      this.isBatchConflationEnabled = in.readBoolean();
      this.isPersistenceEnabled = in.readBoolean();
      this.alertThreshold = in.readInt();
      this.manualStart = in.readBoolean();
      this.eventFiltersClassNames = DataSerializer.readArrayList(in);
      this.transFiltersClassNames = DataSerializer.readArrayList(in);
      this.senderEventListenerClassNames = DataSerializer.readArrayList(in);
      this.isDiskSynchronous = in.readBoolean();
      this.dispatcherThreads = in.readInt();
      this.orderPolicy = DataSerializer.readObject(in);
      boolean serverLocationFound = DataSerializer.readPrimitiveBoolean(in);
      if (serverLocationFound) {
        this.serverLocation = new ServerLocation();
        InternalDataSerializer.invokeFromData(this.serverLocation, in);
      }
    }

    public void toDataPre_GFE_8_0_0_0(DataOutput out) throws IOException {
      super.toData(out);
      DataSerializer.writeString(Id, out);
      out.writeLong(startTime);
      out.writeInt(remoteDSId);
      out.writeBoolean(isRunning);
      out.writeBoolean(isPrimary);
      out.writeBoolean(isParallel);
      out.writeBoolean(isBatchConflationEnabled);
      out.writeBoolean(isPersistenceEnabled);
      out.writeInt(alertThreshold);
      out.writeBoolean(manualStart);
      DataSerializer.writeArrayList(eventFiltersClassNames, out);
      DataSerializer.writeArrayList(transFiltersClassNames, out);
      DataSerializer.writeArrayList(senderEventListenerClassNames, out);
      out.writeBoolean(isDiskSynchronous);
      // out.writeInt(dispatcherThreads);
      if (isParallel)
        out.writeInt(1);// it was 1 on previous version of gemfire
      else if (orderPolicy == null)
        out.writeInt(1);// it was 1 on previous version of gemfire
      else
        out.writeInt(dispatcherThreads);

      if (isParallel)
        DataSerializer.writeObject(null, out);
      else
        DataSerializer.writeObject(orderPolicy, out);

      boolean serverLocationFound = (this.serverLocation != null);
      DataSerializer.writePrimitiveBoolean(serverLocationFound, out);
      if (serverLocationFound) {
        InternalDataSerializer.invokeToData(serverLocation, out);
      }
    }

    private final static Version[] serializationVersions = new Version[] {Version.GFE_80};

    @Override
    public Version[] getSerializationVersions() {
      return serializationVersions;
    }

    @Override
    public int getDSFID() {
      return GATEWAY_SENDER_PROFILE;
    }

    @Override
    public void processIncoming(DistributionManager dm, String adviseePath, boolean removeProfile,
        boolean exchangeProfiles, final List replyProfiles) {
      Cache cache = GemFireCacheImpl.getInstance();
      if (cache != null) {
        AbstractGatewaySender sender =
            (AbstractGatewaySender) ((GemFireCacheImpl) cache).getGatewaySender(adviseePath);
        handleDistributionAdvisee(sender, removeProfile, exchangeProfiles, replyProfiles);
      }
    }

    @Override
    public void fillInToString(StringBuilder sb) {
      super.fillInToString(sb);
      sb.append("; id=" + this.Id);
      sb.append("; remoteDSName=" + this.remoteDSId);
      sb.append("; isRunning=" + this.isRunning);
      sb.append("; isPrimary=" + this.isPrimary);

    }
  }

  public InternalDistributedMember advisePrimaryGatewaySender() {
    Profile[] snapshot = this.profiles;
    for (Profile profile : snapshot) {
      GatewaySenderProfile sp = (GatewaySenderProfile) profile;
      if (!sp.isParallel && sp.isPrimary) {
        return sp.getDistributedMember();
      }
    }
    return null;
  }

  public void setIsPrimary(boolean isPrimary) {
    this.isPrimary = isPrimary;
  }

  @Override
  public void close() {
    new UpdateAttributesProcessor(this.getAdvisee(), true).distribute(false);
    super.close();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy