package com.linkedin.databus.core; /* * * Copyright 2013 LinkedIn Corp. 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. * */ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import com.linkedin.databus2.core.BackoffTimer; import com.linkedin.databus2.core.BackoffTimerStaticConfig; public class CompoundDatabusComponentStatus extends DatabusComponentStatus { private static final long STATUS_EXPIRY_MS = 5; private long _lastStatusCheckMs = 0; private final Map<String, DatabusComponentStatus> _children = new HashMap<String, DatabusComponentStatus>(); private final Map<String, DatabusComponentStatus> _readOnlyChildren = Collections.unmodifiableMap(_children); protected final List<String> _initializing = new ArrayList<String>(); private final List<String> _initializingRO = Collections.unmodifiableList(_initializing); protected final List<String> _retryingOnError = new ArrayList<String>(); private final List<String> _retryingOnErrorRO = Collections.unmodifiableList(_retryingOnError); protected final List<String> _suspended = new ArrayList<String>(); private final List<String> _suspendedRO = Collections.unmodifiableList(_suspended); protected final List<String> _paused = new ArrayList<String>(); private final List<String> _pausedRO = Collections.unmodifiableList(_paused); protected final List<String> _shutdown = new ArrayList<String>(); private final List<String> _shutdownRO = Collections.unmodifiableList(_shutdown); public CompoundDatabusComponentStatus(String componentName, BackoffTimerStaticConfig errorRetriesConf, Collection<DatabusComponentStatus> children) { super(componentName, errorRetriesConf); addChildren(children); } public CompoundDatabusComponentStatus(String componentName, Status status, String detailedMessage, BackoffTimer errorRetriesCounter, Collection<DatabusComponentStatus> children) { super(componentName, status, detailedMessage, errorRetriesCounter); addChildren(children); } public CompoundDatabusComponentStatus(String componentName, Status status, String detailedMessage, BackoffTimerStaticConfig errorRetriesConf, Collection<DatabusComponentStatus> children) { super(componentName, status, detailedMessage, errorRetriesConf); addChildren(children); } public CompoundDatabusComponentStatus(String componentName, Status status, String detailedMessage, Collection<DatabusComponentStatus> children) { super(componentName, status, detailedMessage); addChildren(children); } public CompoundDatabusComponentStatus(String componentName, Collection<DatabusComponentStatus> children) { super(componentName); addChildren(children); } private void processChildStatus(DatabusComponentStatus child) { switch (child.getStatus()) { case INITIALIZING: _initializing.add(child.getComponentName()); break; case RUNNING: break; //NOOP case ERROR_RETRY: _retryingOnError.add(child.getComponentName()); break; case SUSPENDED_ON_ERROR: _suspended.add(child.getComponentName()); break; case PAUSED: _paused.add(child.getComponentName()); break; case SHUTDOWN: _shutdown.add(child.getComponentName()); break; } } private void resetStatusLists() { _initializing.clear(); _retryingOnError.clear(); _suspended.clear(); _paused.clear(); _shutdown.clear(); } public void addChildren(Collection<DatabusComponentStatus> children) { if (null == children) return; for (DatabusComponentStatus child: children) { addChild(child); } } public void addChild(DatabusComponentStatus child) { _children.put(child.getComponentName(), child); processChildStatus(child); } public Map<String, DatabusComponentStatus> getChildren() { return _readOnlyChildren; } public List<String> getInitializing() { return _initializingRO; } public List<String> getSuspended() { return _suspendedRO; } public List<String> getPaused() { return _pausedRO; } public List<String> getShutdown() { return _shutdownRO; } public List<String> getRetryingOnError() { return _retryingOnErrorRO; } @Override public Status getStatus() { refreshStatus(); return super.getStatus(); } @Override public String getMessage() { refreshStatus(); return super.getMessage(); } @Override public DatabusComponentStatus getStatusSnapshot() { refreshStatus(); return super.getStatusSnapshot(); } @Override public boolean isRunningStatus() { refreshStatus(); return super.isRunningStatus(); } @Override public boolean isPausedStatus() { refreshStatus(); return super.isPausedStatus(); } @Override public synchronized void start() { for (Map.Entry<String, DatabusComponentStatus> entry: _children.entrySet()) { try { entry.getValue().start(); } catch (RuntimeException e) { entry.getValue().suspendOnError(e); } } super.start(); refreshStatus(); } @Override public void shutdown() { for (Map.Entry<String, DatabusComponentStatus> entry: _children.entrySet()) { try { entry.getValue().shutdown(); } catch (RuntimeException e) { entry.getValue().suspendOnError(e); } } super.shutdown(); refreshStatus(); } @Override public void pause() { for (Map.Entry<String, DatabusComponentStatus> entry: _children.entrySet()) { try { entry.getValue().pause(); } catch (RuntimeException e) { entry.getValue().suspendOnError(e); } } super.pause(); refreshStatus(); } @Override public void resume() { for (Map.Entry<String, DatabusComponentStatus> entry: _children.entrySet()) { try { entry.getValue().resume(); } catch (RuntimeException e) { entry.getValue().suspendOnError(e); } } super.resume(); refreshStatus(); } @Override public void suspendOnError(Throwable error) { super.suspendOnError(error); refreshStatus(); } public synchronized void refreshStatus() { long now = System.currentTimeMillis(); if ((now - _lastStatusCheckMs) < STATUS_EXPIRY_MS) return; //use cached version _lastStatusCheckMs = now; resetStatusLists(); for (Map.Entry<String, DatabusComponentStatus> entry: _children.entrySet()) { processChildStatus(entry.getValue()); } } }