All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.uima.ducc.ws.WebServerComponent Maven / Gradle / Ivy

The newest version!
/*
 * 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.
*/
package org.apache.uima.ducc.ws;

import java.io.File;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.camel.CamelContext;
import org.apache.uima.ducc.common.NodeIdentity;
import org.apache.uima.ducc.common.boot.DuccDaemonRuntimeProperties;
import org.apache.uima.ducc.common.boot.DuccDaemonRuntimeProperties.DaemonName;
import org.apache.uima.ducc.common.component.AbstractDuccComponent;
import org.apache.uima.ducc.common.config.CommonConfiguration;
import org.apache.uima.ducc.common.head.IDuccHead;
import org.apache.uima.ducc.common.head.IDuccHead.DuccHeadTransition;
import org.apache.uima.ducc.common.internationalization.Messages;
import org.apache.uima.ducc.common.main.DuccService;
import org.apache.uima.ducc.common.utils.DuccLogger;
import org.apache.uima.ducc.common.utils.IDuccLoggerComponents.Daemon;
import org.apache.uima.ducc.common.utils.id.DuccId;
import org.apache.uima.ducc.transport.dispatcher.DuccEventDispatcher;
import org.apache.uima.ducc.transport.event.DaemonDuccEvent;
import org.apache.uima.ducc.transport.event.DuccEvent.EventType;
import org.apache.uima.ducc.transport.event.DuccJobsStateEvent;
import org.apache.uima.ducc.transport.event.NodeMetricsUpdateDuccEvent;
import org.apache.uima.ducc.transport.event.OrchestratorStateDuccEvent;
import org.apache.uima.ducc.transport.event.PmStateDuccEvent;
import org.apache.uima.ducc.transport.event.RmStateDuccEvent;
import org.apache.uima.ducc.transport.event.SmHeartbeatDuccEvent;
import org.apache.uima.ducc.transport.event.SmStateDuccEvent;
import org.apache.uima.ducc.transport.event.common.DuccWorkMap;
import org.apache.uima.ducc.transport.event.common.IDuccWorkMap;
import org.apache.uima.ducc.ws.registry.ServicesRegistry;
import org.apache.uima.ducc.ws.self.message.WebServerStateDuccEvent;
import org.apache.uima.ducc.ws.server.DuccListeners;
import org.apache.uima.ducc.ws.server.DuccWebServer;
import org.apache.uima.ducc.ws.server.DuccWebServerHelper;
import org.apache.uima.ducc.ws.utils.DatedNodeMetricsUpdateDuccEvent;


public class WebServerComponent extends AbstractDuccComponent 
implements IWebServer {
	
	private static DuccLogger duccLogger = DuccLogger.getLogger(WebServerComponent.class);
	
	private static DuccId jobid = null;
	
	private DuccWebServer duccWebServer = null;
	private Messages duccMsg= Messages.getInstance();
	
	private static AtomicInteger jobCount = new AtomicInteger(0);
	private static AtomicInteger serviceCount = new AtomicInteger(0);
	private static AtomicInteger reservationCount = new AtomicInteger(0);
	
	private static AtomicLong updateLast = new AtomicLong(System.currentTimeMillis());
	public static long updateIntervalSecondsInitial = 5;
	public static long updateIntervalSecondsNormal = 60;
	public static AtomicLong updateIntervalCount = new AtomicLong(0);
	public static long updateIntervalLimit = 12;
	
	private DuccEventDispatcher eventDispatcher;
	private String stateChangeEndpoint;

	private IDuccHead dh = null;
	
	public WebServerComponent(CamelContext context, CommonConfiguration common) {
		super("WebServer",context);
		String methodName = "WebServerComponent";
		duccLogger.info(methodName, jobid, "##### boot #####");
		
		String cp = System.getProperty("java.class.path");
		String[] cpArray = cp.split(":");
		int lc = 0;
		for(String line : cpArray) {
			duccLogger.trace(methodName, jobid, "cp."+lc+" "+line);
			lc++;
		}
		
		String[] propertyNames = { "ducc.broker.url" };
		for(String property : propertyNames) {
			duccLogger.info(methodName, jobid, property+"="+System.getProperty(property));
		}
		duccLogger.info(methodName, jobid, System.getProperty("ducc.broker.url"));
		duccWebServer = new DuccWebServer(common);
		init();
	}
	
    /**
     * Tell Orchestrator about state change for recording into system-events.log
     */
    private void stateChange(EventType eventType) {
    	String methodName = "stateChange";
        try {
    		Daemon daemon = Daemon.WebServer;
    		NodeIdentity nodeIdentity = new NodeIdentity();
        	DaemonDuccEvent ev = new DaemonDuccEvent(daemon, eventType, nodeIdentity);
            eventDispatcher.dispatch(stateChangeEndpoint, ev, "");
            duccLogger.info(methodName, null, stateChangeEndpoint, eventType.name(), nodeIdentity.getCanonicalName());
        }
    	catch(Exception e) {
    		duccLogger.error(methodName, null, e);
    	}
    }

	public void start(DuccService service, String[] args) throws Exception {
		super.start(service, args);
		DuccDaemonRuntimeProperties.getInstance().boot(DaemonName.Webserver,getProcessJmxUrl());
        stateChange(EventType.BOOT);
	}
	
	public void stop() throws Exception {
		stateChange(EventType.SHUTDOWN);
		super.stop();
	}
	
	public void setDuccEventDispatcher(DuccEventDispatcher eventDispatcher) {
		this.eventDispatcher = eventDispatcher;
	}
	
	public void setStateChangeEndpoint(String stateChangeEndpoint) {
		this.stateChangeEndpoint = stateChangeEndpoint;
	}
	
	public DuccLogger getLogger() {
	    return duccLogger;
	  }
	public void webServerStart() {
		String methodName = "webServerStart";
		try {
			duccWebServer.start();
			duccLogger.info(methodName, jobid, "webserver started");
		} catch (Exception e) {
			duccLogger.error(methodName, jobid, e);
		}
	}
	
	public void webServerStop() {
		String methodName = "webServerStop";
		try {
			duccWebServer.stop();
			duccLogger.info(methodName, jobid, "webserver stopped");
		} catch (Exception e) {
			duccLogger.error(methodName, jobid, e);
		}
	}
	
	private void init() {
		String methodName = "init";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		File file = new File(DuccWebServerHelper.getDuccWebLogsDir());
		file.mkdirs();
		webServerStart();
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}
	
	private IDuccHead getDuccHead() {
    	if(dh == null) {
    		dh = DuccHead.getInstance();
    		if(dh.is_ducc_head_backup()) {
    			stateChange(EventType.INIT_AS_BACKUP);
    		}
    		else {
    			stateChange(EventType.INIT_AS_MASTER);
    		}
    	}
    	return dh;
    }
	
	public void update(OrchestratorStateDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"OrchestratorStateDuccEvent");
		
		DuccHeadTransition transition = getDuccHead().transition();
		switch(transition) {
		case master_to_master:
			duccLogger.debug(methodName, jobid, "ducc head == master");
			break;
		case master_to_backup:
			DuccData.reset();
			duccEvent.setWorkMap(new DuccWorkMap());	// ignore OR map
			duccLogger.warn(methodName, jobid, "ducc head -> backup");
			stateChange(EventType.SWITCH_TO_BACKUP);
			break;
		case backup_to_master:
			duccLogger.warn(methodName, jobid, "ducc head -> master");
			stateChange(EventType.SWITCH_TO_MASTER);
			DuccBoot.boot();
			break;
		case backup_to_backup:
			duccEvent.setWorkMap(new DuccWorkMap());	// ignore OR map
			duccLogger.debug(methodName, jobid, "ducc head == backup");
			break;
		default:
			duccLogger.debug(methodName, jobid, "ducc head == unspecified");
			break;
		}
		
		DuccDaemonsData.getInstance().put(duccEvent);
		IDuccWorkMap wm = duccEvent.getWorkMap();
		boolean change = false;
		int count;
		count = wm.getJobCount();
		if(count != jobCount.get()) {
			jobCount.set(count);
			change = true;
		}
		count = wm.getReservationCount();
		if(count != reservationCount.get()) {
			reservationCount.set(count);
			change = true;
		}
		count = wm.getServiceCount();
		if(count !=serviceCount.get()) {
			serviceCount.set(count);
			change = true;
		}
		if(change) {
			duccLogger.info(methodName, jobid, duccMsg.fetchLabel("jobs")+jobCount.get()+" "+duccMsg.fetchLabel("reservations")+reservationCount.get()+" "+duccMsg.fetchLabel("services")+serviceCount.get());
		}
		DuccData.getInstance().put(wm);
		DuccPlugins.getInstance().update(wm);
		DuccListeners.getInstance().update(duccEvent);
		Map map = Distiller.deriveMachineMemoryInUse(duccEvent);
		report(map);
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}

	private void report(Map map) {
		String location = "report";
		for(Entry entry : map.entrySet()) {
			duccLogger.trace(location, jobid, entry.getKey()+"="+entry.getValue());
		}
	}
	
	/**
	 * Sort machines if interval has elapsed (60 seconds) 
	 * 
	 * Note: Use an initial short interval (e.g. every 5 seconds)
	 * when the Web Server first boots in order to populate quickly.
	 * After N (e.g. 12) quick recalculations, revert to the normal
	 * interval (e.g. every 60 seconds).
	 */
	private void sortMachines() {
		String methodName = "sortMachines";
		long last = updateLast.get();
		long updateIntervalMilliSeconds = updateIntervalSecondsNormal * 1000;
		if(updateIntervalCount.get() < updateIntervalLimit) {
			updateIntervalMilliSeconds = updateIntervalSecondsInitial * 1000;
		}
		long deadline = last + updateIntervalMilliSeconds;
		long now = System.currentTimeMillis();
		if(now > deadline) {
			boolean success = updateLast.compareAndSet(last, now);
			if(success) {
				DuccMachinesData.getInstance().updateSortedMachines();
				updateIntervalCount.incrementAndGet();
				duccLogger.trace(methodName, jobid, "count: "+updateIntervalCount.get());
			}
			else {
				duccLogger.trace(methodName, jobid, "missed: "+"last="+last+" "+"now="+now);
			}
		}
		else {
			duccLogger.trace(methodName, jobid, "togo: "+(deadline - now)/1000);
		}
	}
	
	public void update(NodeMetricsUpdateDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.trace(methodName, jobid, duccMsg.fetchLabel("received")+"NodeMetricsUpdateDuccEvent");
		DuccMachinesData dmd = DuccMachinesData.getInstance();
		DatedNodeMetricsUpdateDuccEvent datedEvent = new DatedNodeMetricsUpdateDuccEvent(duccEvent);
		dmd.put(datedEvent);
		sortMachines();
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}

	
	public void update(RmStateDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"RmStateDuccEvent");
		DuccDaemonsData.getInstance().put(duccEvent);
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}
	
	
	public void update(SmStateDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"SmStateDuccEvent");
		DuccDaemonsData.getInstance().put(duccEvent);
		ServicesRegistry.getInstance().update();
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}
	
	
	public void update(DuccJobsStateEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"DuccJobsStateEvent");
		DuccDaemonsData.getInstance().put(duccEvent);
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}
	
	
	public void update(PmStateDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"PmStateDuccEvent");
		DuccDaemonsData.getInstance().put(duccEvent);
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}
	
	/**
	 * process the received self-publication (broker is alive!)
	 */
	public void update(WebServerStateDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"WebServerStateDuccEvent (broker is alive)");
		DuccDaemonsData.getInstance().put(duccEvent);
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}

	@Override
	public void update(SmHeartbeatDuccEvent duccEvent) {
		String methodName = "update";
		duccLogger.trace(methodName, jobid, duccMsg.fetch("enter"));
		duccLogger.debug(methodName, jobid, duccMsg.fetchLabel("received")+"SmHeartbeatDuccEvent (SM is alive)");
		DuccDaemonsData.getInstance().put(duccEvent);
		duccLogger.trace(methodName, jobid, duccMsg.fetch("exit"));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy