Package org.apache.helix.api.accessor

Source Code of org.apache.helix.api.accessor.AtomicClusterAccessor

package org.apache.helix.api.accessor;

/*
* 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.
*/

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.helix.HelixDataAccessor;
import org.apache.helix.PropertyKey;
import org.apache.helix.api.Cluster;
import org.apache.helix.api.Participant;
import org.apache.helix.api.Resource;
import org.apache.helix.api.Scope;
import org.apache.helix.api.config.ClusterConfig;
import org.apache.helix.api.config.ParticipantConfig;
import org.apache.helix.api.config.ResourceConfig;
import org.apache.helix.api.id.ClusterId;
import org.apache.helix.api.id.ParticipantId;
import org.apache.helix.api.id.ResourceId;
import org.apache.helix.lock.HelixLock;
import org.apache.helix.lock.HelixLockable;
import org.apache.log4j.Logger;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
* An atomic version of the ClusterAccessor. If atomic operations are required, use instances of
* this class. Atomicity is not guaranteed when using instances of ClusterAccessor alongside
* instances of this class. Furthermore, depending on the semantics of the lock, lock acquisition
* may fail, in which case users should handle the return value of each function if necessary. <br/>
* <br/>
* Using this class is quite expensive; it should thus be used sparingly and only in systems where
* contention on these operations is expected. For most systems running Helix, this is typically not
* the case.
*/
public class AtomicClusterAccessor extends ClusterAccessor {
  private static final Logger LOG = Logger.getLogger(AtomicClusterAccessor.class);

  private final HelixLockable _lockProvider;
  private final HelixDataAccessor _accessor;
  private final PropertyKey.Builder _keyBuilder;
  private final ClusterId _clusterId;

  /**
   * Non-atomic instance to protect against reentrant locking via polymorphism
   */
  private final ClusterAccessor _clusterAccessor;

  /**
   * Instantiate the accessor
   * @param clusterId the cluster to access
   * @param accessor a HelixDataAccessor for the physical properties
   * @param lockProvider a lock provider
   */
  public AtomicClusterAccessor(ClusterId clusterId, HelixDataAccessor accessor,
      HelixLockable lockProvider) {
    super(clusterId, accessor);
    _lockProvider = lockProvider;
    _accessor = accessor;
    _keyBuilder = accessor.keyBuilder();
    _clusterId = clusterId;
    _clusterAccessor = new ClusterAccessor(clusterId, accessor);
  }

  @Override
  public boolean createCluster(ClusterConfig cluster) {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.cluster(_clusterId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.createCluster(cluster);
      } finally {
        lock.unlock();
      }
    }
    return false;
  }

  @Override
  public boolean dropCluster() {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.cluster(_clusterId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.dropCluster();
      } finally {
        lock.unlock();
      }
    }
    return false;
  }

  @Override
  public Cluster readCluster() {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.cluster(_clusterId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.readCluster();
      } finally {
        lock.unlock();
      }
    }
    return null;
  }

  @Override
  public boolean addParticipantToCluster(ParticipantConfig participant) {
    if (participant == null) {
      LOG.error("Participant config cannot be null");
      return false;
    }
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.participant(participant.getId()));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.addParticipantToCluster(participant);
      } finally {
        lock.unlock();
      }
    }
    return false;
  }

  @Override
  public boolean dropParticipantFromCluster(ParticipantId participantId) {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.participant(participantId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.dropParticipantFromCluster(participantId);
      } finally {
        lock.unlock();
      }
    }
    return false;
  }

  @Override
  public boolean addResourceToCluster(ResourceConfig resource) {
    if (resource == null) {
      LOG.error("Resource config cannot be null");
      return false;
    }
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.resource(resource.getId()));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.addResourceToCluster(resource);
      } finally {
        lock.unlock();
      }
    }
    return false;
  }

  @Override
  public boolean dropResourceFromCluster(ResourceId resourceId) {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.resource(resourceId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.dropResourceFromCluster(resourceId);
      } finally {
        lock.unlock();
      }
    }
    return false;
  }

  @Override
  public ClusterConfig updateCluster(ClusterConfig.Delta clusterDelta) {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.cluster(_clusterId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        return _clusterAccessor.updateCluster(clusterDelta);
      } finally {
        lock.unlock();
      }
    }
    return null;
  }

  /**
   * Read resources atomically. This is resource-atomic, not cluster-atomic
   */
  @Override
  public Map<ResourceId, Resource> readResources() {
    // read resources individually instead of together to maintain the equality link between ideal
    // state and resource config
    Map<ResourceId, Resource> resources = Maps.newHashMap();
    Set<String> idealStateNames =
        Sets.newHashSet(_accessor.getChildNames(_keyBuilder.idealStates()));
    Set<String> resourceConfigNames =
        Sets.newHashSet(_accessor.getChildNames(_keyBuilder.resourceConfigs()));
    resourceConfigNames.addAll(idealStateNames);
    ResourceAccessor accessor = new AtomicResourceAccessor(_clusterId, _accessor, _lockProvider);
    for (String resourceName : resourceConfigNames) {
      ResourceId resourceId = ResourceId.from(resourceName);
      Resource resource = accessor.readResource(resourceId);
      if (resource != null) {
        resources.put(resourceId, resource);
      }
    }
    return resources;
  }

  /**
   * Read participants atomically. This is participant-atomic, not cluster-atomic
   */
  @Override
  public Map<ParticipantId, Participant> readParticipants() {
    // read participants individually to keep configs consistent with current state and messages
    Map<ParticipantId, Participant> participants = Maps.newHashMap();
    ParticipantAccessor accessor =
        new AtomicParticipantAccessor(_clusterId, _accessor, _lockProvider);
    List<String> participantNames = _accessor.getChildNames(_keyBuilder.instanceConfigs());
    for (String participantName : participantNames) {
      ParticipantId participantId = ParticipantId.from(participantName);
      Participant participant = accessor.readParticipant(participantId);
      if (participant != null) {
        participants.put(participantId, participant);
      }
    }
    return participants;
  }

  @Override
  public void initClusterStructure() {
    HelixLock lock = _lockProvider.getLock(_clusterId, Scope.cluster(_clusterId));
    boolean locked = lock.lock();
    if (locked) {
      try {
        _clusterAccessor.initClusterStructure();
      } finally {
        lock.unlock();
      }
    }
  }
}
TOP

Related Classes of org.apache.helix.api.accessor.AtomicClusterAccessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.