/* * Copyright 2014-2016 CyberVision, Inc. * * 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. */ package org.kaaproject.kaa.server.control.service.loadmgmt; import org.kaaproject.kaa.server.control.service.loadmgmt.dynamicmgmt.Rebalancer; import org.kaaproject.kaa.server.control.service.zk.ControlZkService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** * Load Distribution Service startup Class. * * @author Andrey Panasenko */ @Service public class LoadDistributionService extends Thread { private static final Logger LOG = LoggerFactory.getLogger(LoadDistributionService.class); /** * Synchronization object. */ private final Object sync = new Object(); /** * boolean used to control operation mode in Thread run() cycle. */ private volatile boolean operate = false; /** * boolean which used to switch on/off recalculation, set try if Control Server is master. */ private volatile boolean isMaster = false; private ControlZkService zkService; private DynamicLoadManager loadManager; /** * Load mgmt data recalculation period. */ @Value("#{properties[recalculation_period]}") private int recalculationPeriod; /** * Time to live of Operations server load history, in sec. */ @Value("#{properties[ops_server_history_ttl]}") private int opsServerHistoryTtl; /** * The dynamic_mgmt. */ @Autowired private Rebalancer rebalancer; /* (non-Javadoc) * @see java.lang.Thread#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("\nLoad Distribution Service properties:\n"); sb.append("\trecalculation_period: " + recalculationPeriod + "\n"); sb.append("\tops_server_history_ttl: " + opsServerHistoryTtl + "\n"); return sb.toString(); } /** * Starts LoadDistributionService. */ @Override public void start() { LOG.info("Load distribution service starting..."); LOG.info(this.toString()); loadManager = new DynamicLoadManager(this); if (zkService != null) { loadManager.registerListeners(); isMaster = zkService.getControlZkNode().isMaster(); LOG.trace("Load Distribution Service isMaster " + isMaster); operate = true; super.start(); } else { LOG.error("Load distribution service start failed, ZK Service not set."); } } /** * Stop LoadDistributionService. */ public void shutdown() { LOG.info("Load distribution service shutdown..."); operate = false; loadManager.deregisterListeners(); synchronized (sync) { sync.notify(); } try { this.join(10000); } catch (InterruptedException ex) { LOG.trace("Load distribution service shutdown join() interrupted"); } finally { LOG.info("Load distribution service shutdown complete"); loadManager = null; } } /** * LoadDistributionService extends Thread * Main run() cycle. * Operation controlled by operate Boolean and recalculate server list and redirection rules. */ @Override public void run() { while (operate) { synchronized (sync) { try { LOG.info("Load distribution service recalculation started..."); loadManager.recalculate(); sync.wait(recalculationPeriod * 1000); } catch (InterruptedException ex) { LOG.warn("Load distribution service interrupted, shutting down..."); operate = false; } } } LOG.info("Load distribution service stopped"); } /** * Gets the recalculation_period. * * @return the recalculation_period */ public int getRecalculationPeriod() { return recalculationPeriod; } /** * Sets the recalculation_period. * * @param recalculationPeriod the recalculation period to set */ public void setRecalculationPeriod(int recalculationPeriod) { this.recalculationPeriod = recalculationPeriod; } /** * Checks if is master. * * @return boolean the isMaster */ public boolean isMaster() { return isMaster; } /** * Boolean isMaster control if Load Distribution run load balancing recalculation. * If set to true - run load balancing recalculation. * * @param isMaster the master */ public void setMaster(boolean isMaster) { if (this.isMaster != isMaster) { this.isMaster = isMaster; LOG.info("Load distribution service master state changed from {} to {}", this.isMaster, isMaster); synchronized (sync) { sync.notify(); } } } public Rebalancer getRebalancer() { return rebalancer; } /** * Gets the zk service. * * @return the zkService */ public ControlZkService getZkService() { return zkService; } /** * Sets the zk service. * * @param zkService the zkService to set */ public void setZkService(ControlZkService zkService) { this.zkService = zkService; } /** * Gets the ops_server_history_ttl. * * @return the endpoint_history_ttl */ public int getOpsServerHistoryTtl() { return opsServerHistoryTtl; } }