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

com.gemstone.gemfire.cache.client.internal.ClientMetadataService 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.cache.client.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import com.gemstone.gemfire.SystemFailure;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.EntryOperation;
import com.gemstone.gemfire.cache.FixedPartitionResolver;
import com.gemstone.gemfire.cache.Operation;
import com.gemstone.gemfire.cache.PartitionResolver;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.distributed.internal.ServerLocation;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.cache.BucketServerLocation66;
import com.gemstone.gemfire.internal.cache.EntryOperationImpl;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.cache.LocalRegion;
import com.gemstone.gemfire.internal.cache.PartitionedRegionHelper;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;

/**
 * Maintains {@link ClientPartitionAdvisor} for Partitioned Regions on servers
 * Client operations will consult this service to identify the server locations
 * on which the data for the client operation is residing
 * 
 * @author Suranjan Kumar
 * @author Yogesh Mahajan
 * 
 * @since 6.5
 * 
 */
public final class ClientMetadataService {

  private final LogWriterI18n logger;
  
  private final Cache cache;
  
  private final Set nonPRs = new HashSet();

  private boolean HONOUR_SERVER_GROUP_IN_PR_SINGLE_HOP = Boolean.getBoolean("gemfire.PoolImpl.honourServerGroupsInPRSingleHop");

  public static final int SIZE_BYTES_ARRAY_RECEIVED = 2;
  
  public static final int INITIAL_VERSION = 0;
  
  /** random number generator used in pruning */
  private final Random rand = new Random();
  
  public ClientMetadataService(Cache cache) {
    this.cache = cache;
    this.logger = ((GemFireCacheImpl)cache).getLoggerI18n();
  }

  private final Map clientPRAdvisors = new ConcurrentHashMap();
  private final Map> colocatedPRAdvisors = new ConcurrentHashMap>();
  
  private PartitionResolver getResolver(Region r, Object key,
      Object callbackArgument) {
    // First choice is one associated with the region
    final String regionFullPath = r.getFullPath();
    ClientPartitionAdvisor advisor = this
        .getClientPartitionAdvisor(regionFullPath);
    PartitionResolver result = null;
    if (advisor != null) {
      result = advisor.getPartitionResolver();
    }
    
    if (result != null) {
      return result;
    }

    // Second is the key
    if (key != null && key instanceof PartitionResolver) {
      return (PartitionResolver)key;
    }

    // Third is the callback argument
    if (callbackArgument != null
        && callbackArgument instanceof PartitionResolver) {
      return (PartitionResolver)callbackArgument;
    }
    // There is no resolver.
    return null;
  }

  public ServerLocation getBucketServerLocation(Region region,
      Operation operation, Object key, Object value, Object callbackArg) {
    ClientPartitionAdvisor prAdvisor  = this.getClientPartitionAdvisor(region.getFullPath());
    if (prAdvisor == null) {
      return null;
    }
    int totalNumberOfBuckets = prAdvisor.getTotalNumBuckets();

    final PartitionResolver resolver = getResolver(region, key, callbackArg);
    Object resolveKey;
    EntryOperation entryOp = null;
    if (resolver == null) {
      // client has not registered PartitionResolver
      // Assuming even PR at server side is not using PartitionResolver
      resolveKey = key;
    }
    else {
      entryOp = new EntryOperationImpl(region, operation, key,
          value, callbackArg);
      resolveKey = resolver.getRoutingObject(entryOp);
      if (resolveKey == null) {
        throw new IllegalStateException(
            LocalizedStrings.PartitionedRegionHelper_THE_ROUTINGOBJECT_RETURNED_BY_PARTITIONRESOLVER_IS_NULL
                .toLocalizedString());
      }
    }
    int bucketId;
    if (resolver instanceof FixedPartitionResolver) {
      if (entryOp == null) {
        entryOp = new EntryOperationImpl(region,
            Operation.FUNCTION_EXECUTION, key, null, null);
      }
      String partition = ((FixedPartitionResolver)resolver).getPartitionName(
          entryOp, prAdvisor.getFixedPartitionNames());
      if (partition == null) {
        Object[] prms = new Object[] { region.getName(), resolver };
        throw new IllegalStateException(
            LocalizedStrings.PartitionedRegionHelper_FOR_REGION_0_PARTITIONRESOLVER_1_RETURNED_PARTITION_NAME_NULL
                .toLocalizedString(prms));
      }
      else {
        bucketId = prAdvisor.assignFixedBucketId(region, partition, resolveKey);
        if (bucketId == -1) {
          // scheduleGetPRMetaData((LocalRegion)region);
          return null;
        }

      }
    }else {
      bucketId = PartitionedRegionHelper.getHashKey(resolveKey, totalNumberOfBuckets);
    }
    
    ServerLocation bucketServerLocation = getServerLocation(region, operation,
        bucketId);
    ServerLocation location = null;
    if (bucketServerLocation != null)
      location = new ServerLocation(bucketServerLocation.getHostName(),
          bucketServerLocation.getPort());
    return location;
  }

  private ServerLocation getServerLocation(Region region, Operation operation,
      int bucketId) {
    final String regionFullPath = region.getFullPath();
    ClientPartitionAdvisor prAdvisor = this.getClientPartitionAdvisor(regionFullPath);
    if (prAdvisor == null) {
      if (this.logger.fineEnabled()) {
        this.logger.fine(
            "ClientMetadataService#getServerLocation : Region "
                + regionFullPath + "prAdvisor does not exist.");
      }
      return null;
    }
    
//    if (prAdvisor.getColocatedWith() != null) {
//      prAdvisor = this.getClientPartitionAdvisor(prAdvisor.getColocatedWith());
//      if (prAdvisor == null) {
//        if (this.logger.fineEnabled()) {
//          this.logger.fine(
//              "ClientMetadataService#getServerLocation : Region "
//                  + regionFullPath + "prAdvisor does not exist.");
//        }
//        return null;
//      }
//    }
    
    if (operation.isGet()) {
      return prAdvisor.adviseServerLocation(bucketId);
    }
    else {
      return prAdvisor.advisePrimaryServerLocation(bucketId);
    }
  }

  public Map getServerToFilterMap(
      final Collection routingKeys, final Region region, boolean primaryMembersNeeded) {
    final String regionFullPath = region.getFullPath();
    ClientPartitionAdvisor prAdvisor = this.getClientPartitionAdvisor(regionFullPath);
    if (prAdvisor == null || prAdvisor.adviseRandomServerLocation() == null) {
      scheduleGetPRMetaData((LocalRegion)region, false);
      return null;
    }
    HashMap bucketToKeysMap = groupByBucketOnClientSide(
        region, prAdvisor, routingKeys);

    HashMap serverToKeysMap = new HashMap();
    HashMap> serverToBuckets = groupByServerToBuckets(
        prAdvisor, bucketToKeysMap.keySet(), primaryMembersNeeded);
    
    if(serverToBuckets == null){
      return null;
    }
    
    for (Map.Entry entry : serverToBuckets.entrySet()) {
      ServerLocation server = (ServerLocation)entry.getKey();
      HashSet buckets = (HashSet)entry.getValue();
      for (Integer bucket : buckets) {
        // use LinkedHashSet to maintain the order of keys
        // the keys will be iterated several times
        LinkedHashSet keys = (LinkedHashSet)serverToKeysMap.get(server);
        if (keys == null) {
          keys = new LinkedHashSet();
        }
        keys.addAll(bucketToKeysMap.get(bucket));
        serverToKeysMap.put(server, keys);
      }
    }
    if (this.logger.fineEnabled()) {
      this.logger.fine("Returning server to keys map : " + serverToKeysMap);
    }

    return serverToKeysMap;
  }
  
  public HashMap> groupByServerToAllBuckets(Region region, boolean primaryOnly){
    final String regionFullPath = region.getFullPath();
    ClientPartitionAdvisor prAdvisor = this.getClientPartitionAdvisor(regionFullPath);
    if (prAdvisor == null || prAdvisor.adviseRandomServerLocation() == null) {
      scheduleGetPRMetaData((LocalRegion)region, false);
      return null;
    }
    int totalNumberOfBuckets = prAdvisor.getTotalNumBuckets();
    HashSet allBucketIds = new HashSet();
    for(int i =0; i < totalNumberOfBuckets; i++){
      allBucketIds.add(i);
    }
    return groupByServerToBuckets(prAdvisor, allBucketIds, primaryOnly);
  }
  /**
   * This function should make a map of server to buckets it is hosting.
   * If for some bucket servers are not available due to mismatch in metadata
   * it should fill up a random server for it.
   */
  private HashMap> groupByServerToBuckets(
      ClientPartitionAdvisor prAdvisor, Set bucketSet,
      boolean primaryOnly) {
    if (primaryOnly) {
      Set bucketsWithoutServer = new HashSet();
      HashMap> serverToBucketsMap = new HashMap>();
      for (Integer bucketId : bucketSet) {
        ServerLocation server = prAdvisor.advisePrimaryServerLocation(bucketId);
        if (server == null) {
          bucketsWithoutServer.add(bucketId);
          continue;
        }
        HashSet buckets = serverToBucketsMap.get(server);
        if (buckets == null) {
          buckets = new HashSet(); // faster if this was an ArrayList
          serverToBucketsMap.put(server, buckets);
        }
        buckets.add(bucketId);
      }

      if (!serverToBucketsMap.isEmpty()) {
        serverToBucketsMap.entrySet().iterator().next().getValue().addAll(
            bucketsWithoutServer);
      }
      
      if (this.logger.fineEnabled()) {
        this.logger
            .fine("ClientMetadataService: The server to bucket map is : "
                + serverToBucketsMap);
      }

      return serverToBucketsMap;
    }
    else {
      return pruneNodes(prAdvisor, bucketSet);
    }
  }
  
  
  private HashMap> pruneNodes(
      ClientPartitionAdvisor prAdvisor, Set buckets) {

    if (this.logger.fineEnabled()) {
      this.logger.fine("ClientMetadataService: The buckets to be pruned are: "
          + buckets);
    }
    Set bucketSetWithoutServer = new HashSet();
    HashMap> serverToBucketsMap = new HashMap>();
    HashMap> prunedServerToBucketsMap = new HashMap>();

    for (Integer bucketId : buckets) {
      List serversList = prAdvisor
          .adviseServerLocations(bucketId);
      if (this.logger.fineEnabled()) {
        this.logger.fine("ClientMetadataService: For bucketId  " + bucketId
            + " the server list is  " + serversList);
      }
      if (serversList == null || serversList.size() == 0) {
        bucketSetWithoutServer.add(bucketId);
        continue;
      }
      
      if (this.logger.fineEnabled()) {
        this.logger.fine("ClientMetadataService: The buckets owners of the bucket: "
            + bucketId + " are: " + serversList);
      }
      
      for (ServerLocation server : serversList) {
        if (serverToBucketsMap.get(server) == null) {
          HashSet bucketSet = new HashSet();
          bucketSet.add(bucketId);
          serverToBucketsMap.put(server, bucketSet);
        }
        else {
          HashSet bucketSet = serverToBucketsMap.get(server);
          bucketSet.add(bucketId);
          serverToBucketsMap.put(server, bucketSet);
        }
      }
    }
    if (this.logger.fineEnabled()) {
      this.logger.fine("ClientMetadataService: The server to buckets map is :"
          + serverToBucketsMap);
    }

    HashSet currentBucketSet = new HashSet();
    // ServerLocation randomFirstServer =
    // prAdvisor.adviseRandomServerLocation(); // get a random server here
    ServerLocation randomFirstServer = null;
    if (serverToBucketsMap.isEmpty()) {
      return null;
    }
    else {
      int size = serverToBucketsMap.size();
      randomFirstServer = (ServerLocation)serverToBucketsMap.keySet().toArray()[rand.nextInt(size)];
    }
    HashSet bucketSet = serverToBucketsMap.get(randomFirstServer);
    if (this.logger.fineEnabled()) {
      this.logger.fine("ClientMetadataService: Adding the server :"
          + randomFirstServer + " which is random and buckets " + bucketSet
          + " to prunedMap ");
    }
    currentBucketSet.addAll(bucketSet);
    prunedServerToBucketsMap.put(randomFirstServer, bucketSet);
    serverToBucketsMap.remove(randomFirstServer);

    while (!currentBucketSet.equals(buckets)) {
      ServerLocation server = findNextServer(serverToBucketsMap.entrySet(),
          currentBucketSet);
      if (server == null) {
//        HashSet rBuckets = prunedServerToBucketsMap
//            .get(randomFirstServer);
//        HashSet remainingBuckets = new HashSet(buckets);
//        remainingBuckets.removeAll(currentBucketSet);
//        rBuckets.addAll(remainingBuckets);
//        prunedServerToBucketsMap.put(randomFirstServer, rBuckets);
        break;
      }
      
      HashSet bucketSet2 = serverToBucketsMap.get(server);
      bucketSet2.removeAll(currentBucketSet);
      if(bucketSet2.isEmpty()) {
        serverToBucketsMap.remove(server);
        continue;
      }
      currentBucketSet.addAll(bucketSet2);
      prunedServerToBucketsMap.put(server, bucketSet2);
      if (this.logger.fineEnabled()) {
        this.logger.fine("ClientMetadataService: Adding the server :" + server
            + " and buckets " + bucketSet2 + " to prunedServer ");
      }
      serverToBucketsMap.remove(server);
    }
    
    prunedServerToBucketsMap.entrySet().iterator().next().getValue().addAll(
        bucketSetWithoutServer);
    
    if (this.logger.fineEnabled()) {
      this.logger
          .fine("ClientMetadataService: The final prunedServerToBucket calculated is :"
              + prunedServerToBucketsMap);
    }
    
    return prunedServerToBucketsMap;
  }
  
  
  private ServerLocation findNextServer(
      Set>> entrySet,
      HashSet currentBucketSet) {
   
    ServerLocation server = null;
    int max = -1;
    ArrayList nodesOfEqualSize = new ArrayList(); 
    for (Map.Entry> entry : entrySet) {
      HashSet buckets = new HashSet();
      buckets.addAll(entry.getValue());
      buckets.removeAll(currentBucketSet);

      if (max < buckets.size()) {
        max = buckets.size();
        server = entry.getKey();
        nodesOfEqualSize.clear();
        nodesOfEqualSize.add(server);
      }
      else if (max == buckets.size()){
        nodesOfEqualSize.add(server);
      }
    }
    
    //return node;
    Random r = new Random();
    if(nodesOfEqualSize.size() > 0)
      return nodesOfEqualSize.get(r.nextInt(nodesOfEqualSize.size()));
    
    return null; 
  }
  
  private HashMap groupByBucketOnClientSide(Region region,
      ClientPartitionAdvisor prAdvisor, Collection routingKeys) {
    
    HashMap bucketToKeysMap = new HashMap();
    Iterator i = routingKeys.iterator();
    while (i.hasNext()) {
      Object key = i.next();
      int totalNumberOfBuckets = prAdvisor.getTotalNumBuckets();
      final PartitionResolver resolver = getResolver(region, key, null);
      Object resolveKey;
      EntryOperation entryOp = null;
      if (resolver == null) {
        // client has not registered PartitionResolver
        // Assuming even PR at server side is not using PartitionResolver
        resolveKey = key;
      }
      else {
        entryOp = new EntryOperationImpl(region,
            Operation.FUNCTION_EXECUTION, key, null, null);
        resolveKey = resolver.getRoutingObject(entryOp);
        if (resolveKey == null) {
          throw new IllegalStateException(
              LocalizedStrings.PartitionedRegionHelper_THE_ROUTINGOBJECT_RETURNED_BY_PARTITIONRESOLVER_IS_NULL
                  .toLocalizedString());
        }
      }
      int bucketId;
      if (resolver instanceof FixedPartitionResolver) {
        if (entryOp == null) {
          entryOp = new EntryOperationImpl(region,
              Operation.FUNCTION_EXECUTION, key, null, null);
        }
        String partition = ((FixedPartitionResolver)resolver).getPartitionName(
            entryOp, prAdvisor.getFixedPartitionNames());
        if (partition == null) {
          Object[] prms = new Object[] { region.getName(), resolver };
          throw new IllegalStateException(
              LocalizedStrings.PartitionedRegionHelper_FOR_REGION_0_PARTITIONRESOLVER_1_RETURNED_PARTITION_NAME_NULL
                  .toLocalizedString(prms));
        }
        else {
          bucketId =  prAdvisor.assignFixedBucketId(region, partition, resolveKey);
          // This bucketid can be -1 in some circumstances where we don't have information about 
          // all the partition on the server.
          // Do proactive scheduling of metadata fetch
          if(bucketId == -1) {
            scheduleGetPRMetaData((LocalRegion)region, true);
          }
        }
      }else{
        bucketId = PartitionedRegionHelper.getHashKey(resolveKey, totalNumberOfBuckets);
      }
      HashSet bucketKeys = bucketToKeysMap.get(bucketId);
      if (bucketKeys == null) {
        bucketKeys = new HashSet(); // faster if this was an ArrayList
        bucketToKeysMap.put(bucketId, bucketKeys);
      }
      bucketKeys.add(key);
    }
    if (this.logger.fineEnabled()) {
      this.logger.fine("Bucket to keys map : " + bucketToKeysMap);
    }
    return bucketToKeysMap;
  }

  public void scheduleGetPRMetaData(final LocalRegion region,
      final boolean isRecursive) {
    if(this.nonPRs.contains(region.getFullPath())){
      return;
    }
    region.getCachePerfStats().incNonSingleHopsCount();
    if (isRecursive) {
      try {
        getClientPRMetadata(region);
      }
      catch (VirtualMachineError e) {
        SystemFailure.initiateFailure(e);
        throw e;
      }
      catch (Throwable e) {
        SystemFailure.checkFailure();
        if (logger.fineEnabled()) {
          logger.fine("An exception occurred while fetching metadata ", e);
        }
      }
    }
    else {
      Runnable fetchTask = new Runnable() {
        @SuppressWarnings("synthetic-access")
        public void run() {
          try {
            getClientPRMetadata(region);
          }
          catch (VirtualMachineError e) {
            SystemFailure.initiateFailure(e);
            throw e;
          }
          catch (Throwable e) {
            SystemFailure.checkFailure();
            if (logger.fineEnabled()) {
              logger.fine("An exception occurred while fetching metadata", e);
            }
          }
        }
      };
      SingleHopClientExecutor.submitTask(fetchTask);
    }
  }
  
  public final void getClientPRMetadata(LocalRegion region) {
    isMetadataRefreshed_TEST_ONLY = true;
    final String regionFullPath = region.getFullPath();
    ClientPartitionAdvisor advisor = null;
    InternalPool pool = region.getServerProxy().getPool();
    // Acquires lock only if it is free, else a request to fetch meta data is in
    // progress, so just return 
    if (region.clientMetaDataLock.tryLock()) {
      try {
        advisor = this.getClientPartitionAdvisor(regionFullPath);
        if (advisor==null) {
          advisor = GetClientPartitionAttributesOp
              .execute(pool, regionFullPath);
          if(advisor == null){
            this.nonPRs.add(regionFullPath);
            return;
          }
          addClientPartitionAdvisor(regionFullPath, advisor);
        }
        else {
          if(advisor.getFixedPAMap() != null && !advisor.isFPAAttrsComplete()) {
            ClientPartitionAdvisor newAdvisor = GetClientPartitionAttributesOp
            .execute(pool, regionFullPath);
            advisor.updateFixedPAMap(newAdvisor.getFixedPAMap());
          }
        }
        String colocatedWith = advisor.getColocatedWith();
        if (colocatedWith == null) {
          GetClientPRMetaDataOp.execute(pool, regionFullPath, this);
          region.getCachePerfStats().incMetaDataRefreshCount();
        }
        else {
          ClientPartitionAdvisor colocatedAdvisor = this.getClientPartitionAdvisor(colocatedWith);
          LocalRegion leaderRegion = (LocalRegion)region.getCache()
          .getRegion(colocatedWith);
          if (colocatedAdvisor == null) {
            scheduleGetPRMetaData(leaderRegion, true);
            return;
          }
          else {
            GetClientPRMetaDataOp.execute(pool, colocatedWith, this);
            leaderRegion.getCachePerfStats().incMetaDataRefreshCount();
          }
        }
      }
      finally {
        region.clientMetaDataLock.unlock();
      }
    }
  }
  
  public void scheduleGetPRMetaData(final LocalRegion region,
      final boolean isRecursive, byte nwHopType) {
    if(this.nonPRs.contains(region.getFullPath())){
      return;
    }
    ClientPartitionAdvisor advisor = this.getClientPartitionAdvisor(region.getFullPath());
    if(advisor!= null && advisor.getServerGroup().length()!= 0 && HONOUR_SERVER_GROUP_IN_PR_SINGLE_HOP){
      if (logger.fineEnabled()) {
        logger.fine("Scheduling metadata refresh :" + nwHopType);
      }
      if(nwHopType == (byte)2){
        return;
      }
    }
    region.getCachePerfStats().incNonSingleHopsCount();
    if (isRecursive) {
      try {
        getClientPRMetadata(region);
      } catch (VirtualMachineError e) {
        SystemFailure.initiateFailure(e);
        throw e;
      } catch (Throwable e) {
        SystemFailure.checkFailure();
        if (logger.fineEnabled()) {
          logger.fine("An exception occurred while fetching metadata", e);
        }
      }
    } else {
      Runnable fetchTask = new Runnable() {
        @SuppressWarnings("synthetic-access")
        public void run() {
          try {
            getClientPRMetadata(region);
          } catch (VirtualMachineError e) {
            SystemFailure.initiateFailure(e);
            throw e;
          } catch (Throwable e) {
            SystemFailure.checkFailure();
            if (logger.fineEnabled()) {
              logger
                  .fine("An exception occurred while fetching metadata", e);
            }
          }
        }
      };
      SingleHopClientExecutor.submitTask(fetchTask);
    }
  }

  public void removeBucketServerLocation(ServerLocation serverLocation) {
    Set keys = getAllRegionFullPaths();
    if (logger.fineEnabled()) {
      logger.fine("ClientMetadataService removing a ServerLocation :"
          + serverLocation + keys);
    }
    if (keys != null) {
      for (String regionPath : keys) {
        ClientPartitionAdvisor prAdvisor = this
            .getClientPartitionAdvisor(regionPath);
        if (logger.fineEnabled()) {
          logger.fine("ClientMetadataService removing from "
              + regionPath + prAdvisor);
        }
        if (prAdvisor != null) {
          prAdvisor.removeBucketServerLocation(serverLocation);
        }
      }
    }
  }
  
  public byte getMetaDataVersion(Region region, Operation operation,
      Object key, Object value, Object callbackArg) {
    ClientPartitionAdvisor prAdvisor = this.getClientPartitionAdvisor(region
        .getFullPath());
    if (prAdvisor == null) {
      return 0;
    }

    int totalNumberOfBuckets = prAdvisor.getTotalNumBuckets();

    final PartitionResolver resolver = getResolver(region, key, callbackArg);
    Object resolveKey;
    EntryOperation entryOp = null;
    if (resolver == null) {
      // client has not registered PartitionResolver
      // Assuming even PR at server side is not using PartitionResolver
      resolveKey = key;
    }
    else {
      entryOp = new EntryOperationImpl(region, operation, key,
          value, callbackArg);
      resolveKey = resolver.getRoutingObject(entryOp);
      if (resolveKey == null) {
        throw new IllegalStateException(
            LocalizedStrings.PartitionedRegionHelper_THE_ROUTINGOBJECT_RETURNED_BY_PARTITIONRESOLVER_IS_NULL
                .toLocalizedString());
      }
    }
    
    int bucketId;
    if (resolver instanceof FixedPartitionResolver) {
      if (entryOp == null) {
        entryOp = new EntryOperationImpl(region,
            Operation.FUNCTION_EXECUTION, key, null, null);
      }
      String partition = ((FixedPartitionResolver)resolver).getPartitionName(
          entryOp, prAdvisor.getFixedPartitionNames());
      if (partition == null) {
        Object[] prms = new Object[] { region.getName(), resolver };
        throw new IllegalStateException(
            LocalizedStrings.PartitionedRegionHelper_FOR_REGION_0_PARTITIONRESOLVER_1_RETURNED_PARTITION_NAME_NULL
                .toLocalizedString(prms));
      }
      else {
        bucketId =  prAdvisor.assignFixedBucketId(region, partition, resolveKey);
      }
    }else {
      bucketId = PartitionedRegionHelper.getHashKey(resolveKey, totalNumberOfBuckets);
    }
    
    BucketServerLocation66 bsl = (BucketServerLocation66)getPrimaryServerLocation(
        region, bucketId);
    if (bsl == null) {
      return 0;
    }
    return bsl.getVersion();
  }

  private ServerLocation getPrimaryServerLocation(Region region, int bucketId) {
    final String regionFullPath = region.getFullPath();
    ClientPartitionAdvisor prAdvisor = this.getClientPartitionAdvisor(regionFullPath);
    if (prAdvisor == null) {
      if (this.logger.fineEnabled()) {
        this.logger.fine("ClientMetadataService#getServerLocation : Region "
            + regionFullPath + " prAdvisor does not exist.");
      }
      return null;
    }

    if (prAdvisor.getColocatedWith() != null) {
      prAdvisor = this.getClientPartitionAdvisor(prAdvisor.getColocatedWith());
      if (prAdvisor == null) {
        if (this.logger.fineEnabled()) {
          this.logger.fine("ClientMetadataService#getServerLocation : Region "
              + regionFullPath + " prAdvisor does not exist.");
        }
        return null;
      }
    }
    return prAdvisor.advisePrimaryServerLocation(bucketId);
  }
  
  private void addClientPartitionAdvisor(String regionFullPath,
      ClientPartitionAdvisor advisor) {
    if (this.cache.isClosed() || this.clientPRAdvisors == null) {
      return;
    }
    try {
      this.clientPRAdvisors.put(regionFullPath, advisor);
      if (advisor.getColocatedWith() != null) {
        String parentRegionPath = advisor.getColocatedWith();
        Set colocatedAdvisors = this.colocatedPRAdvisors.get(parentRegionPath);
        if(colocatedAdvisors == null){
          colocatedAdvisors = new CopyOnWriteArraySet();
          this.colocatedPRAdvisors.put(parentRegionPath, colocatedAdvisors);
        }
        colocatedAdvisors.add(advisor);
      }
    }
    catch (Exception npe) {
      // ignore, shutdown case
    }
    
  }

  public ClientPartitionAdvisor getClientPartitionAdvisor(String regionFullPath) {
    if (this.cache.isClosed() || this.clientPRAdvisors == null) {
      return null;
    }
    ClientPartitionAdvisor prAdvisor = null;
    try {
      prAdvisor = this.clientPRAdvisors.get(regionFullPath);
    }
    catch (Exception npe) {
      return null;
    }
    return prAdvisor;
  }
  
  public Set getColocatedClientPartitionAdvisor(String regionFullPath) {
    if (this.cache.isClosed() || this.clientPRAdvisors == null || this.colocatedPRAdvisors == null) {
      return null;
    }
    return this.colocatedPRAdvisors.get(regionFullPath);
  }
  
  private Set getAllRegionFullPaths() {
    if (this.cache.isClosed() || this.clientPRAdvisors == null) {
      return null;
    }
    Set keys  = null;
    try {
      keys = this.clientPRAdvisors.keySet();
    }
    catch (Exception npe) {
      return null;
    }
    return keys;
  }

  public void close() {
    this.clientPRAdvisors.clear();
    this.colocatedPRAdvisors.clear();
  }
  
  public boolean isRefreshMetadataTestOnly() {
    return isMetadataRefreshed_TEST_ONLY;
  }

  public void satisfyRefreshMetadata_TEST_ONLY(boolean isRefreshMetadataTestOnly) {
    isMetadataRefreshed_TEST_ONLY = isRefreshMetadataTestOnly;
  }

  public Map getClientPRMetadata_TEST_ONLY() {
    return clientPRAdvisors;
  }

  public Map getClientPartitionAttributesMap() {
    return clientPRAdvisors;
  }

  public boolean honourServerGroup(){
    return HONOUR_SERVER_GROUP_IN_PR_SINGLE_HOP;
  }
  
  private boolean isMetadataRefreshed_TEST_ONLY = false;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy