Ejemplo n.º 1
0
  protected Cache<String, String> startCache() throws IOException {
    CacheBuilder cb = new CacheBuilder(cfgFile);
    EmbeddedCacheManager cacheManager = cb.getCacheManager();
    Configuration dcc = cacheManager.getDefaultCacheConfiguration();

    cacheManager.defineConfiguration(
        "wordcount",
        new ConfigurationBuilder()
            .read(dcc)
            .clustering()
            .l1()
            .disable()
            .clustering()
            .cacheMode(CacheMode.DIST_SYNC)
            .hash()
            .numOwners(1)
            .build());
    Cache<String, String> cache = cacheManager.getCache();

    Transport transport = cache.getAdvancedCache().getRpcManager().getTransport();
    if (isMaster)
      System.out.printf(
          "Node %s joined as master. View is %s.%n",
          transport.getAddress(), transport.getMembers());
    else
      System.out.printf(
          "Node %s joined as slave. View is %s.%n", transport.getAddress(), transport.getMembers());

    return cache;
  }
 @Start(priority = 25) // after the distribution manager!
 @SuppressWarnings("unused")
 private void setAddress() {
   this.address = transport.getAddress();
   this.isUsingLockDelegation =
       !cacheConfiguration.transaction().transactionMode().isTransactional();
 }
  private void recoverClusterStatus(
      int newViewId, boolean isMergeView, List<Address> clusterMembers) throws Exception {
    ReplicableCommand command =
        new CacheTopologyControlCommand(
            null, CacheTopologyControlCommand.Type.GET_STATUS, transport.getAddress(), newViewId);
    Map<Address, Object> statusResponses =
        executeOnClusterSync(command, getGlobalTimeout(), false, false);

    log.debugf("Got %d status responses. members are %s", statusResponses.size(), clusterMembers);
    Map<String, Map<Address, CacheStatusResponse>> responsesByCache = new HashMap<>();
    for (Map.Entry<Address, Object> responseEntry : statusResponses.entrySet()) {
      Address sender = responseEntry.getKey();
      Map<String, CacheStatusResponse> nodeStatus =
          (Map<String, CacheStatusResponse>) responseEntry.getValue();
      for (Map.Entry<String, CacheStatusResponse> statusEntry : nodeStatus.entrySet()) {
        String cacheName = statusEntry.getKey();

        Map<Address, CacheStatusResponse> cacheResponses = responsesByCache.get(cacheName);
        if (cacheResponses == null) {
          cacheResponses = new HashMap<>();
          responsesByCache.put(cacheName, cacheResponses);
        }
        cacheResponses.put(sender, statusEntry.getValue());
      }
    }

    for (Map.Entry<String, Map<Address, CacheStatusResponse>> e : responsesByCache.entrySet()) {
      ClusterCacheStatus cacheStatus = initCacheStatusIfAbsent(e.getKey());
      cacheStatus.doMergePartitions(e.getValue(), clusterMembers, isMergeView);
    }
  }
 protected void fetchRebalancingStatusFromCoordinator() {
   if (!transport.isCoordinator()) {
     ReplicableCommand command =
         new CacheTopologyControlCommand(
             null,
             CacheTopologyControlCommand.Type.POLICY_GET_STATUS,
             transport.getAddress(),
             transport.getViewId());
     Address coordinator = transport.getCoordinator();
     try {
       Map<Address, Response> responseMap =
           transport.invokeRemotely(
               Collections.singleton(coordinator),
               command,
               ResponseMode.SYNCHRONOUS,
               getGlobalTimeout(),
               null,
               DeliverOrder.NONE,
               false);
       Response response = responseMap.get(coordinator);
       if (response instanceof SuccessfulResponse) {
         globalRebalancingEnabled = ((Boolean) ((SuccessfulResponse) response).getResponseValue());
       } else {
         log.errorReadingRebalancingStatus(coordinator, null);
       }
     } catch (Exception e) {
       log.errorReadingRebalancingStatus(coordinator, e);
     }
   }
 }
 private void confirmMembersAvailable() throws Exception {
   ReplicableCommand heartbeatCommand =
       new CacheTopologyControlCommand(
           null, CacheTopologyControlCommand.Type.POLICY_GET_STATUS, transport.getAddress(), -1);
   transport.invokeRemotely(
       null,
       heartbeatCommand,
       ResponseMode.SYNCHRONOUS,
       getGlobalTimeout(),
       null,
       DeliverOrder.NONE,
       false);
 }
 @Override
 public void broadcastRebalanceStart(
     String cacheName, CacheTopology cacheTopology, boolean totalOrder, boolean distributed) {
   CLUSTER.startRebalance(cacheName, cacheTopology);
   ReplicableCommand command =
       new CacheTopologyControlCommand(
           cacheName,
           CacheTopologyControlCommand.Type.REBALANCE_START,
           transport.getAddress(),
           cacheTopology,
           null,
           transport.getViewId());
   executeOnClusterAsync(command, getGlobalTimeout(), totalOrder, distributed);
 }
  private void recoverClusterStatus(
      int newViewId, final boolean isMergeView, final List<Address> clusterMembers)
      throws Exception {
    log.debugf("Recovering cluster status for view %d", newViewId);
    ReplicableCommand command =
        new CacheTopologyControlCommand(
            null, CacheTopologyControlCommand.Type.GET_STATUS, transport.getAddress(), newViewId);
    Map<Address, Object> statusResponses =
        executeOnClusterSync(
            command, getGlobalTimeout(), false, false, new CacheTopologyFilterReuser());

    log.debugf("Got %d status responses. members are %s", statusResponses.size(), clusterMembers);
    Map<String, Map<Address, CacheStatusResponse>> responsesByCache = new HashMap<>();
    boolean recoveredRebalancingStatus = true;
    for (Map.Entry<Address, Object> responseEntry : statusResponses.entrySet()) {
      Address sender = responseEntry.getKey();
      ManagerStatusResponse nodeStatus = (ManagerStatusResponse) responseEntry.getValue();
      recoveredRebalancingStatus &= nodeStatus.isRebalancingEnabled();
      for (Map.Entry<String, CacheStatusResponse> statusEntry : nodeStatus.getCaches().entrySet()) {
        String cacheName = statusEntry.getKey();
        Map<Address, CacheStatusResponse> cacheResponses = responsesByCache.get(cacheName);
        if (cacheResponses == null) {
          cacheResponses = new HashMap<>();
          responsesByCache.put(cacheName, cacheResponses);
        }
        cacheResponses.put(sender, statusEntry.getValue());
      }
    }

    globalRebalancingEnabled = recoveredRebalancingStatus;
    // Compute the new consistent hashes on separate threads
    int maxThreads = Runtime.getRuntime().availableProcessors() / 2 + 1;
    CompletionService<Void> cs =
        new SemaphoreCompletionService<>(asyncTransportExecutor, maxThreads);
    for (final Map.Entry<String, Map<Address, CacheStatusResponse>> e :
        responsesByCache.entrySet()) {
      final ClusterCacheStatus cacheStatus = initCacheStatusIfAbsent(e.getKey());
      cs.submit(
          new Callable<Void>() {
            @Override
            public Void call() throws Exception {
              cacheStatus.doMergePartitions(e.getValue(), clusterMembers, isMergeView);
              return null;
            }
          });
    }
    for (int i = 0; i < responsesByCache.size(); i++) {
      cs.take();
    }
  }
  // needs to be AFTER the RpcManager
  // The DMI is cache-scoped, so it will always start after the RMI, which is global-scoped
  @Start(priority = 20)
  private void join() throws Exception {
    if (trace) log.trace("starting distribution manager on " + getMyAddress());
    notifier.addListener(listener);

    Transport t = rpcManager.getTransport();
    List<Address> members = t.getMembers();
    self = t.getAddress();
    lastViewId = t.getViewId();
    consistentHash = ConsistentHashHelper.createConsistentHash(configuration, members);
    lastSuccessfulCH = ConsistentHashHelper.createConsistentHash(configuration, members);

    // in case we are/become the coordinator, make sure we're in the push confirmations map before
    // anyone else
    synchronized (pushConfirmations) {
      pushConfirmations.put(t.getAddress(), -1);
    }

    // allow incoming requests
    joinStartedLatch.countDown();

    // nothing to push, but we need to inform the coordinator that we have finished our push
    notifyCoordinatorPushCompleted(t.getViewId());
  }
 @Override
 public void broadcastStableTopologyUpdate(
     String cacheName, CacheTopology cacheTopology, boolean totalOrder, boolean distributed) {
   log.debugf(
       "Updating cluster-wide stable topology for cache %s, topology = %s",
       cacheName, cacheTopology);
   ReplicableCommand command =
       new CacheTopologyControlCommand(
           cacheName,
           CacheTopologyControlCommand.Type.STABLE_TOPOLOGY_UPDATE,
           transport.getAddress(),
           cacheTopology,
           null,
           transport.getViewId());
   executeOnClusterAsync(command, getGlobalTimeout(), totalOrder, distributed);
 }
  @Start(priority = 11) // after Transport
  public void start() {
    SecurityActions.addCacheManagerListener(cache.getCacheManager(), new RankCalculator());

    isClustered =
        SecurityActions.getCacheConfiguration(cache.getAdvancedCache())
            .clustering()
            .cacheMode()
            .isClustered();

    if (isClustered) {
      // Use component registry to avoid keeping an instance ref simply used on start
      ComponentRegistry componentRegistry =
          SecurityActions.getCacheComponentRegistry(cache.getAdvancedCache());
      Transport transport =
          componentRegistry.getGlobalComponentRegistry().getComponent(Transport.class);
      calculateRank(transport.getAddress(), transport.getMembers(), transport.getViewId());
    }
  }
 @Override
 public void broadcastTopologyUpdate(
     String cacheName,
     CacheTopology cacheTopology,
     AvailabilityMode availabilityMode,
     boolean totalOrder,
     boolean distributed) {
   log.debugf(
       "Updating cluster-wide current topology for cache %s, topology = %s, availability mode = %s",
       cacheName, cacheTopology, availabilityMode);
   ReplicableCommand command =
       new CacheTopologyControlCommand(
           cacheName,
           CacheTopologyControlCommand.Type.CH_UPDATE,
           transport.getAddress(),
           cacheTopology,
           availabilityMode,
           transport.getViewId());
   executeOnClusterAsync(command, getGlobalTimeout(), totalOrder, distributed);
 }
 public void testInvokeRemotelyWhenSingleMember() throws Exception {
   Cache cache1 = cache(0, "replSync");
   Transport mockTransport = createMock(Transport.class);
   RpcManagerImpl rpcManager =
       (RpcManagerImpl) TestingUtil.extractComponent(cache1, RpcManager.class);
   Transport originalTransport = TestingUtil.extractComponent(cache1, Transport.class);
   try {
     Address mockAddress1 = createNiceMock(Address.class);
     List<Address> memberList = new ArrayList<Address>(1);
     memberList.add(mockAddress1);
     expect(mockTransport.getMembers()).andReturn(memberList).anyTimes();
     expect(mockTransport.getAddress()).andReturn(null).anyTimes();
     rpcManager.setTransport(mockTransport);
     // Transport invoke remote should not be called.
     replay(mockAddress1, mockTransport);
     // now try a simple replication.  Since the RpcManager is a mock object it will not actually
     // replicate anything.
     cache1.put(key, value);
     verify(mockTransport);
   } finally {
     if (rpcManager != null) rpcManager.setTransport(originalTransport);
   }
 }
  private Map<Address, Object> executeOnClusterSync(
      final ReplicableCommand command, final int timeout, boolean totalOrder, boolean distributed)
      throws Exception {
    // first invoke remotely

    if (totalOrder) {
      Map<Address, Response> responseMap =
          transport.invokeRemotely(
              transport.getMembers(),
              command,
              ResponseMode.SYNCHRONOUS_IGNORE_LEAVERS,
              timeout,
              false,
              null,
              totalOrder,
              distributed);
      Map<Address, Object> responseValues =
          new HashMap<Address, Object>(transport.getMembers().size());
      for (Map.Entry<Address, Response> entry : responseMap.entrySet()) {
        Address address = entry.getKey();
        Response response = entry.getValue();
        if (!response.isSuccessful()) {
          Throwable cause =
              response instanceof ExceptionResponse
                  ? ((ExceptionResponse) response).getException()
                  : null;
          throw new CacheException(
              "Unsuccessful response received from node " + address + ": " + response, cause);
        }
        responseValues.put(address, ((SuccessfulResponse) response).getResponseValue());
      }
      return responseValues;
    }

    Future<Map<Address, Response>> remoteFuture =
        asyncTransportExecutor.submit(
            new Callable<Map<Address, Response>>() {
              @Override
              public Map<Address, Response> call() throws Exception {
                return transport.invokeRemotely(
                    null,
                    command,
                    ResponseMode.SYNCHRONOUS_IGNORE_LEAVERS,
                    timeout,
                    true,
                    null,
                    false,
                    false);
              }
            });

    // invoke the command on the local node
    gcr.wireDependencies(command);
    Response localResponse;
    try {
      if (log.isTraceEnabled()) log.tracef("Attempting to execute command on self: %s", command);
      localResponse = (Response) command.perform(null);
    } catch (Throwable throwable) {
      throw new Exception(throwable);
    }
    if (!localResponse.isSuccessful()) {
      throw new CacheException("Unsuccessful local response: " + localResponse);
    }

    // wait for the remote commands to finish
    Map<Address, Response> responseMap = remoteFuture.get(timeout, TimeUnit.MILLISECONDS);

    // parse the responses
    Map<Address, Object> responseValues =
        new HashMap<Address, Object>(transport.getMembers().size());
    for (Map.Entry<Address, Response> entry : responseMap.entrySet()) {
      Address address = entry.getKey();
      Response response = entry.getValue();
      if (!response.isSuccessful()) {
        Throwable cause =
            response instanceof ExceptionResponse
                ? ((ExceptionResponse) response).getException()
                : null;
        throw new CacheException(
            "Unsuccessful response received from node " + address + ": " + response, cause);
      }
      responseValues.put(address, ((SuccessfulResponse) response).getResponseValue());
    }

    responseValues.put(
        transport.getAddress(), ((SuccessfulResponse) localResponse).getResponseValue());

    return responseValues;
  }