Search in sources :

Example 1 with BaseDataAccessor

use of org.apache.helix.BaseDataAccessor in project pinot by linkedin.

the class HelixHelper method updateIdealState.

/**
   * Updates the ideal state, retrying if necessary in case of concurrent updates to the ideal state.
   *
   * @param helixManager The HelixManager used to interact with the Helix cluster
   * @param resourceName The resource for which to update the ideal state
   * @param updater A function that returns an updated ideal state given an input ideal state
   */
public static void updateIdealState(final HelixManager helixManager, final String resourceName, final Function<IdealState, IdealState> updater, RetryPolicy policy) {
    boolean successful = policy.attempt(new Callable<Boolean>() {

        @Override
        public Boolean call() {
            HelixDataAccessor dataAccessor = helixManager.getHelixDataAccessor();
            PropertyKey propertyKey = dataAccessor.keyBuilder().idealStates(resourceName);
            // Create an updated version of the ideal state
            IdealState idealState = dataAccessor.getProperty(propertyKey);
            PropertyKey key = dataAccessor.keyBuilder().idealStates(resourceName);
            String path = key.getPath();
            // Make a copy of the the idealState above to pass it to the updater, instead of querying again,
            // as the state my change between the queries.
            ZNRecordSerializer znRecordSerializer = new ZNRecordSerializer();
            IdealState idealStateCopy = new IdealState((ZNRecord) znRecordSerializer.deserialize(znRecordSerializer.serialize(idealState.getRecord())));
            IdealState updatedIdealState;
            try {
                updatedIdealState = updater.apply(idealStateCopy);
            } catch (Exception e) {
                LOGGER.error("Caught exception while updating ideal state", e);
                return false;
            }
            // If there are changes to apply, apply them
            if (!EqualityUtils.isEqual(idealState, updatedIdealState) && updatedIdealState != null) {
                BaseDataAccessor<ZNRecord> baseDataAccessor = dataAccessor.getBaseDataAccessor();
                boolean success;
                // If the ideal state is large enough, enable compression
                if (MAX_PARTITION_COUNT_IN_UNCOMPRESSED_IDEAL_STATE < updatedIdealState.getPartitionSet().size()) {
                    updatedIdealState.getRecord().setBooleanField("enableCompression", true);
                }
                try {
                    success = baseDataAccessor.set(path, updatedIdealState.getRecord(), idealState.getRecord().getVersion(), AccessOption.PERSISTENT);
                } catch (Exception e) {
                    boolean idealStateIsCompressed = updatedIdealState.getRecord().getBooleanField("enableCompression", false);
                    LOGGER.warn("Caught exception while updating ideal state for resource {} (compressed={}), retrying.", resourceName, idealStateIsCompressed, e);
                    return false;
                }
                if (success) {
                    return true;
                } else {
                    LOGGER.warn("Failed to update ideal state for resource {}, retrying.", resourceName);
                    return false;
                }
            } else {
                LOGGER.warn("Idempotent or null ideal state update for resource {}, skipping update.", resourceName);
                return true;
            }
        }
    });
    if (!successful) {
        throw new RuntimeException("Failed to update ideal state for resource " + resourceName);
    }
}
Also used : BaseDataAccessor(org.apache.helix.BaseDataAccessor) IdealState(org.apache.helix.model.IdealState) HelixDataAccessor(org.apache.helix.HelixDataAccessor) PropertyKey(org.apache.helix.PropertyKey) ZNRecord(org.apache.helix.ZNRecord) ZNRecordSerializer(org.apache.helix.manager.zk.ZNRecordSerializer)

Example 2 with BaseDataAccessor

use of org.apache.helix.BaseDataAccessor in project helix by apache.

the class CallbackHandler method subscribeForChanges.

private void subscribeForChanges(NotificationContext.Type callbackType, String path, boolean watchChild) {
    long start = System.currentTimeMillis();
    if (_eventTypes.contains(EventType.NodeDataChanged) || _eventTypes.contains(EventType.NodeCreated) || _eventTypes.contains(EventType.NodeDeleted)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Subscribing data change listener to path:" + path);
        }
        subscribeDataChange(path, callbackType);
    }
    if (_eventTypes.contains(EventType.NodeChildrenChanged)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Subscribing child change listener to path:" + path);
        }
        subscribeChildChange(path, callbackType);
        if (watchChild) {
            if (logger.isDebugEnabled()) {
                logger.debug("Subscribing data change listener to all children for path:" + path);
            }
            try {
                switch(_changeType) {
                    case CURRENT_STATE:
                    case IDEAL_STATE:
                    case EXTERNAL_VIEW:
                    case TARGET_EXTERNAL_VIEW:
                        {
                            // check if bucketized
                            BaseDataAccessor<ZNRecord> baseAccessor = new ZkBaseDataAccessor<>(_zkClient);
                            List<ZNRecord> records = baseAccessor.getChildren(path, null, 0);
                            for (ZNRecord record : records) {
                                HelixProperty property = new HelixProperty(record);
                                String childPath = path + "/" + record.getId();
                                int bucketSize = property.getBucketSize();
                                if (bucketSize > 0) {
                                    // subscribe both data-change and child-change on bucketized parent node
                                    // data-change gives a delete-callback which is used to remove watch
                                    subscribeChildChange(childPath, callbackType);
                                    subscribeDataChange(childPath, callbackType);
                                    // subscribe data-change on bucketized child
                                    List<String> bucketizedChildNames = _zkClient.getChildren(childPath);
                                    if (bucketizedChildNames != null) {
                                        for (String bucketizedChildName : bucketizedChildNames) {
                                            String bucketizedChildPath = childPath + "/" + bucketizedChildName;
                                            subscribeDataChange(bucketizedChildPath, callbackType);
                                        }
                                    }
                                } else {
                                    subscribeDataChange(childPath, callbackType);
                                }
                            }
                            break;
                        }
                    default:
                        {
                            List<String> childNames = _zkClient.getChildren(path);
                            if (childNames != null) {
                                for (String childName : childNames) {
                                    String childPath = path + "/" + childName;
                                    subscribeDataChange(childPath, callbackType);
                                }
                            }
                            break;
                        }
                }
            } catch (ZkNoNodeException e) {
                logger.warn("fail to subscribe child/data change. path: " + path + ", listener: " + _listener, e);
            }
        }
    }
    long end = System.currentTimeMillis();
    logger.info("Subscribing to path:" + path + " took:" + (end - start));
}
Also used : ZkNoNodeException(org.I0Itec.zkclient.exception.ZkNoNodeException) HelixProperty(org.apache.helix.HelixProperty) BaseDataAccessor(org.apache.helix.BaseDataAccessor) List(java.util.List) ZNRecord(org.apache.helix.ZNRecord)

Aggregations

BaseDataAccessor (org.apache.helix.BaseDataAccessor)2 ZNRecord (org.apache.helix.ZNRecord)2 List (java.util.List)1 ZkNoNodeException (org.I0Itec.zkclient.exception.ZkNoNodeException)1 HelixDataAccessor (org.apache.helix.HelixDataAccessor)1 HelixProperty (org.apache.helix.HelixProperty)1 PropertyKey (org.apache.helix.PropertyKey)1 ZNRecordSerializer (org.apache.helix.manager.zk.ZNRecordSerializer)1 IdealState (org.apache.helix.model.IdealState)1