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

com.gemstone.gemfire.internal.cache.GridAdvisor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You
 * may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. See accompanying
 * LICENSE file.
 */

package com.gemstone.gemfire.internal.cache;

import java.util.*;
import java.io.*;

import com.gemstone.gemfire.*;
import com.gemstone.gemfire.distributed.DistributedSystemDisconnectedException;
import com.gemstone.gemfire.distributed.Locator;
import com.gemstone.gemfire.distributed.internal.*;
import com.gemstone.gemfire.distributed.internal.DistributionAdvisor.Profile;
import com.gemstone.gemfire.distributed.internal.membership.*;


/**
 * Used to share code with BridgeServerAdvisor and ControllerAdvisor
 * @author darrel
 *
 */
public abstract class GridAdvisor extends DistributionAdvisor {
  
  /** Creates a new instance of GridAdvisor */
  protected GridAdvisor(DistributionAdvisee server) {
    super(server);
  }

  private final Object cacheLock = new Object();
  private volatile List/**/ cachedBridgeServerProfiles;
  private volatile List/**/ cachedControllerProfiles;
  private volatile Set/**/ cachedBridgeServerAdvise;
  private volatile Set/**/ cachedControllerAdvise;

  private static final Filter CONTROLLER_FILTER = new Filter() {
      public boolean include(Profile profile) {
        return profile instanceof ControllerAdvisor.ControllerProfile;
      }
    };

  private static final Filter BRIDGE_SERVER_FILTER = new Filter() {
      public boolean include(Profile profile) {
        return profile instanceof BridgeServerAdvisor.BridgeServerProfile;
      }
    };
  
  /**
   * Return an unmodifiable Set of the cnx controllers
   * in this system.
   */
  public Set adviseControllers() {
    Set/**/ result = this.cachedControllerAdvise;
    if (result == null) {
      synchronized (this.cacheLock) {
        result = this.cachedControllerAdvise;
        if (result == null) {
          result = Collections.unmodifiableSet(adviseFilter(CONTROLLER_FILTER));
          this.cachedControllerAdvise = result;
        }
      }
    }
    return result;
  }

  /**
   * Return an unmodifiable Set of the bridge servers
   * in this system.
   */
  public Set adviseBridgeServers() {
    Set/**/ result = this.cachedBridgeServerAdvise;
    if (result == null) {
      synchronized (this.cacheLock) {
        result = this.cachedBridgeServerAdvise;
        if (result == null) {
          result = Collections.unmodifiableSet(adviseFilter(BRIDGE_SERVER_FILTER));
          this.cachedBridgeServerAdvise = result;
        }
      }
    }
    return result;
  }

  /**
   * Returns an unmodifiable List of the
   * BridgeServerProfiles for all known bridge servers.
   */
  public List/**/ fetchBridgeServers() {
    List/**/ result = null; //this.cachedBridgeServerProfiles;
    if (result == null) {
      synchronized (this.cacheLock) {
//        result = this.cachedBridgeServerProfiles;
        if (result == null) {
          result = fetchProfiles(BRIDGE_SERVER_FILTER);
          this.cachedBridgeServerProfiles = result;
        }
      }
    }
    return result;
  }
  /**
   * Returns an unmodifiable List of the
   * ControllerProfiles for all known cnx controllers.
   */
  public List/**/ fetchControllers() {
    List/**/ result = this.cachedControllerProfiles;
    if (result == null) {
      synchronized (this.cacheLock) {
        result = this.cachedControllerProfiles;
        if (result == null) {
          result = fetchProfiles(CONTROLLER_FILTER);
          this.cachedControllerProfiles = result;
        }
      }
    }
    return result;
  }

  public int getBridgeServerCount() {
    List/**/ l = this.cachedBridgeServerProfiles;
    if (l == null) {
      l = fetchProfiles(BRIDGE_SERVER_FILTER);
    }
    return l.size();
  }

  public int getControllerCount() {
    List/**/ l = this.cachedControllerProfiles;
    if (l == null) {
      l = fetchProfiles(CONTROLLER_FILTER);
    }
    return l.size();
  }

  /**
   * Need ALL others (both normal members and admin members).
   */
  @Override
  public boolean useAdminMembersForDefault() {
    return true;
  }

  /**
   * Just always return true.
   * This method could use getAllOtherMembers but it would cause
   * us to make lots of copies of the member set.
   * The problem with our super.isCurrentMember is it ignores admin members.
   */
  @Override
  protected boolean isCurrentMember(Profile p) {
    return true;
  }

  @Override
  protected void profileCreated(Profile profile) {
    profilesChanged();
  }
  @Override
  protected void profileUpdated(Profile profile) {
    profilesChanged();
  }
  @Override
  protected void profileRemoved(Profile profile) {
    profilesChanged();
  }
  /**
   * Used to drop any cached profile views we have since the master list
   * of profiles changed. The next time someone asks for a view it will
   * be recomputed.
   */
  protected void profilesChanged() {
    if (pollIsInitialized()) {
      // no need to synchronize here since all cached* fields are volatile
      this.cachedBridgeServerProfiles = null;
      this.cachedControllerProfiles = null;
      this.cachedBridgeServerAdvise = null;
      this.cachedControllerAdvise = null;
    }
  }

  /**
   * Tell everyone else who we are and find out who they are.
   */
  public void handshake() {
    if(initializationGate()) {
      //Exchange with any local servers or controllers.
      List otherProfiles = new ArrayList();
      GridProfile profile = (GridProfile) createProfile();
      profile.tellLocalBridgeServers(false, true, otherProfiles);
      profile.tellLocalControllers(false, true, otherProfiles);
      for(Profile otherProfile : otherProfiles) {
        if(!otherProfile.equals(profile)) {
          this.putProfile(otherProfile);
        }
      }
    }
    profilesChanged();
  }
  
  @Override
  public void close() {
    try {
      new UpdateAttributesProcessor(getAdvisee(),
                                    true/*removeProfile*/).distribute();
      
      //Notify any local bridge servers or controllers
      //that we are closing.
      GridProfile profile = (GridProfile) createProfile();
      profile.tellLocalBridgeServers(true, false, null);
      profile.tellLocalControllers(true, false, null);
      super.close();
    } catch (DistributedSystemDisconnectedException ignore) {
      // we are closing so ignore a shutdown exception.
    }
    profilesChanged();
  }
  
  
  
  @Override
  public Set adviseProfileRemove() {
    //Our set of profiles includes local members. However, the update
    //attributes message doesn't seem to be able to handle being sent to local
    //members
    Set results = super.adviseProfileRemove();
    results.remove(getDistributionManager().getId());
    return results;
  }



  /**
   * Describes profile data common for all Grid resources
   */
  public static abstract class GridProfile extends DistributionAdvisor.Profile {

    private String host;

    /**
     * GemFireXD uses a negative port value when creating a fake profile meant
     * to only gather information about all available locators.
     */
    private int port;

    private ProfileId id;

    /** for internal use, required for DataSerializer.readObject */
    public GridProfile() {
    }

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

    public GridProfile(GridProfile toCopy) {
      super(toCopy.getDistributedMember(), toCopy.version);
      this.host = toCopy.host;
      this.port = toCopy.port;
      finishInit();
    }

    public final void setHost(String host) {
      this.host = host;
    }

    public final void setPort(int port) {
      this.port = port;
    }

    public final String getHost() {
      return this.host;
    }

    public final int getPort() {
      return this.port;
    }

    @Override
    public final ProfileId getId() {
      if (this.id == null) throw new IllegalStateException("profile id not yet initialized");
      return this.id;
    }

    /**
     * Tell local controllers about the received profile. Also if exchange
     * profiles then add each local controller to reply.
     * 
     * @since 5.7
     */
    protected final void tellLocalControllers(boolean removeProfile,
        boolean exchangeProfiles, final List replyProfiles) {
      final List locators = Locator.getLocators();
      for (int i = 0; i < locators.size(); i++) {
        InternalLocator l = (InternalLocator)locators.get(i);
        DistributionAdvisee advisee = l.getServerLocatorAdvisee();
        if(advisee != null && advisee.getProfile().equals(this)) {
          continue;
        }
        // negative value for port used by GemFireXD to indicate fake profile
        // meant to only gather remote profiles during profile exchange
        if (this.port > 0) {
          handleDistributionAdvisee(advisee, removeProfile, exchangeProfiles,
              replyProfiles);
        }
        else if (exchangeProfiles && advisee != null) {
          replyProfiles.add(advisee.getProfile());
        }
      }
      final GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
      if (cache != null && !cache.isClosed()) {
        handleDistributionAdvisee(cache.getGfxdAdvisee(), removeProfile, false,
            replyProfiles);
      }
    }

    /**
     * Tell local bridge servers about the received profile. Also if exchange
     * profiles then add each local bridge server to reply.
     * 
     * @since 5.7
     */
    protected final void tellLocalBridgeServers(boolean removeProfile,
        boolean exchangeProfiles, final List replyProfiles) {
      final GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
      if (cache != null && !cache.isClosed()) {
        List bridgeServers = cache.getBridgeServersAndGatewayReceiver();
        for (int i = 0; i < bridgeServers.size(); i++) {
          BridgeServerImpl bsi = (BridgeServerImpl)bridgeServers.get(i);
          if (bsi.isRunning()) {
            if(bsi.getProfile().equals(this)) {
              continue;
            }
            // negative value for port used by GemFireXD to indicate fake
            // profile meant to only gather remote profiles during profile
            // exchange
            if (this.port > 0) {
              handleDistributionAdvisee(bsi, removeProfile, exchangeProfiles,
                  replyProfiles);
            }
            else if (exchangeProfiles) {
              replyProfiles.add(bsi.getProfile());
            }
          }
        }
      }
    }

    @Override
    public void toData(DataOutput out) throws IOException {
      super.toData(out);
      DataSerializer.writeString(this.host, out);
      DataSerializer.writePrimitiveInt(this.port, out);
    }

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.host = DataSerializer.readString(in);
      this.port = DataSerializer.readPrimitiveInt(in);
      finishInit();
    }

    public void finishInit() {
      this.id = new GridProfileId(this);
    }
    
    @Override
    public void fillInToString(StringBuilder sb) {
      super.fillInToString(sb);
      sb.append("; host=" + this.host);
      sb.append("; port=" + this.port);
    }
  }

  /**
   * Basic idea is to base id off of host and port of GridProfile
   */
  public static final class GridProfileId implements ProfileId {

    private final GridProfile gp;

    public GridProfileId(GridProfile gp) {
      this.gp = gp;
    }

    public final InternalDistributedMember getMemberId() {
      return this.gp.getDistributedMember();
    }

    public final String getHost() {
      return this.gp.getHost();
    }

    public final int getPort() {
      return this.gp.getPort();
    }

    @Override
    public String toString() {
      return "GridProfile[host=" + this.gp.getHost() + ",port=" + gp.getPort()
          + ']';
    }

    @Override
    public int hashCode() {
      final String thisHost = this.gp.getHost();
      final int thisPort = this.gp.getPort();
      return thisHost != null ? (thisHost.hashCode() ^ thisPort) : thisPort;
    }

    @Override
    public boolean equals(Object obj) {
      if (obj instanceof GridProfileId) {
        final GridProfileId other = (GridProfileId)obj;
        if (this.gp.getPort() == other.gp.getPort()) {
          final String thisHost = this.gp.getHost();
          final String otherHost = other.gp.getHost();
          if (thisHost != null) {
            return thisHost.equals(otherHost);
          }
          else {
            return (otherHost == null);
          }
        }
      }
      return false;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy