All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.ebay.lightning.core.manager.TaskExecutionManager Maven / Gradle / Ivy
/**
*
*/
package com.ebay.lightning.core.manager;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ebay.lightning.core.async.Callback;
import com.ebay.lightning.core.async.Reminder;
import com.ebay.lightning.core.beans.LightningRequest;
import com.ebay.lightning.core.beans.LightningResponse;
import com.ebay.lightning.core.beans.ReservationReceipt;
import com.ebay.lightning.core.beans.SystemStatus;
import com.ebay.lightning.core.config.RequestConfig;
import com.ebay.lightning.core.config.SystemConfig;
import com.ebay.lightning.core.constants.LightningCoreConstants.WorkStatus;
import com.ebay.lightning.core.exception.ManagerQueueFullException;
import com.ebay.lightning.core.exception.WorkQueueCapacityReachedException;
import com.ebay.lightning.core.store.ExecutionDataStore;
import com.ebay.lightning.core.store.LightningRequestReport;
import com.ebay.lightning.core.utils.InetSocketAddressCache;
import com.ebay.lightning.core.utils.LightningCoreUtil;
import com.ebay.lightning.core.workers.SocketBasedHTTPWorker;
import com.google.common.base.Preconditions;
/**
* The {@code TaskExecutionManager} provides the actual implementation of request processing, reporting and storage.
*
* The requests are queued up and gets processed in FIFO order.
* THe class delegates report storage to {@link ExecutionDataStore}
*
* @author shashukla
*
*/
@Component
public class TaskExecutionManager {
private static final String TASK_EXECUTION_MANAGER_THREAD = "TaskExecutionManagerThread";
private static final Logger log = Logger.getLogger(TaskExecutionManager.class);
private final Object initLock = new Object();
private Boolean started = Boolean.FALSE;
private final SystemConfig systemConfig;
private BlockingQueue workQueue;
private final Map reservationResponseLog = new ConcurrentHashMap<>();
private ExecutionDataStore dataStore;
@SuppressWarnings("unused")
private Reminder reservationCleanupReminder = null;
private Thread queueReader;
private final InetSocketAddressCache inetcache;
@Autowired
public TaskExecutionManager(SystemConfig systemConfig, ExecutionDataStore dataStore, InetSocketAddressCache inetCache) {
this.systemConfig = !systemConfig.isLoadFromFile() ? systemConfig : systemConfig.loadFromFile();
this.dataStore = dataStore;
this.inetcache = inetCache;
workQueue = new LinkedBlockingQueue(systemConfig.getMaxTaskCapacity());
}
/**
* Initialized the {@code TaskExecutionManager} with reservation cleanup {@link Reminder} and request processing thread.
*/
@PostConstruct
public void start() {
synchronized (initLock) {
if (started) {
return;
} else {
started = true;
}
}
reservationCleanupReminder = new Reminder("ReservationCleanupReminder", new Callback() {
@Override
public void notify(String arg) {
for (java.util.Map.Entry entry : reservationResponseLog.entrySet()) {
if (entry.getValue() < System.currentTimeMillis()) {
reservationResponseLog.remove(entry.getKey());
}
}
}
}, systemConfig.getOldReservationCleanupReminderTimeInMillis() / 1000L, true);
queueReader = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
processEntireWorkQueue();
sleepFor(systemConfig.getTimeToSleepBetweenEachQueueProcessInMillis());
} catch (Exception e) {
log.error("Error in executing qd requests", e);
}
}
}
private void processEntireWorkQueue() {
while (!workQueue.isEmpty()) {
LightningRequest request = null;
try {
//Just peak, it will be polled only after successful completion
request = workQueue.peek();
LightningRequestReport report = dataStore.getReport(request.getSessionId());
report.setWorkDequeueTime(System.currentTimeMillis());
long startTime = System.currentTimeMillis();
report.setProcessStartTime(startTime);
loadDefaultsInRequestConfig(request);
SocketBasedHTTPWorker worker = new SocketBasedHTTPWorker(inetcache, dataStore, systemConfig, request.getRequestconfig());
worker.execute(request.getSessionId());
report.setTotalExecutionTimeInMillis(System.currentTimeMillis() - startTime);
log.info("\n\n" + report);
//all batches are executed, now remove the request from Q
workQueue.poll();
} catch (Exception e) {
log.fatal("Error processing " + request, e);
}
}
}
private void loadDefaultsInRequestConfig(LightningRequest request) {
RequestConfig requestConfig = request.getRequestconfig() != null ? request.getRequestconfig() : new RequestConfig();
requestConfig.loadDefaultValues(systemConfig);
request.setRequestconfig(requestConfig);
}
}, TASK_EXECUTION_MANAGER_THREAD);
queueReader.start();
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#reserve(int)}
*/
public synchronized ReservationReceipt reserve(int load) {
ReservationReceipt reserveResponse = null;
int busyWithLoad = getSubmittedLoad() + getReservedLoad();
int leftoverCapacity = systemConfig.getMaxTaskCapacity() - busyWithLoad;
if (leftoverCapacity >= load) {
if (busyWithLoad > 0) {
reserveResponse = new ReservationReceipt(ReservationReceipt.State.BUSY, UUID.randomUUID().toString(), load);
} else {
reserveResponse = new ReservationReceipt(ReservationReceipt.State.ACCEPTED, UUID.randomUUID().toString(), load);
}
} else {
reserveResponse = new ReservationReceipt(ReservationReceipt.State.DENIED, UUID.randomUUID().toString(), load);
}
long expiryTime = (System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(systemConfig.getReservationResponseExpireTimeInSec()));
reservationResponseLog.put(reserveResponse, expiryTime);
reserveResponse.setBusyWithLoad(busyWithLoad);
return reserveResponse;
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#submit(LightningRequest)}
*/
public void submit(LightningRequest request) {
Preconditions.checkState((request != null), "Request Cannot be null");
Preconditions.checkState((request.getReservationReciept() != null), "Reservation Reciept Cannot be null");
Preconditions.checkState(reservationResponseLog.containsKey(request.getReservationReciept()),
"Unknown Reservation Reciept. Reservation is either expired or never created. %s", request.getReservationReciept());
Preconditions.checkState(!ReservationReceipt.State.DENIED.equals(request.getReservationReciept().getState()),
"Request submission is attemped on a Denied Reservation.");
try {
if (request.getTasks() != null) {
LightningRequestReport report = dataStore.register(request);
workQueue.add(request);
reservationResponseLog.remove(request.getReservationReciept());
report.setWorkEnqueueTime(System.currentTimeMillis());
report.setStatus(WorkStatus.IN_QUEUE);
} else {
throw new WorkQueueCapacityReachedException();
}
} catch (IllegalStateException e) {
throw new ManagerQueueFullException();
}
}
/**
* Sleep for the specified amount of time.
*/
private void sleepFor(long sleepMillis) {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
log.error("Unable to sleep...", e);
}
}
/**
* Get the work load to be processed.
* @return the work load to be processed
*/
private int getSubmittedLoad() {
int load = 0;
for (LightningRequest e : workQueue) {
load += e.getRequestSize();
}
return load;
}
/**
* Get the total load of reservation made.
* @return the total load of reservation made
*/
private int getReservedLoad() {
int load = 0;
for (Entry e : reservationResponseLog.entrySet()) {
if (!ReservationReceipt.State.DENIED.equals(e.getKey().getState())) {
load += e.getKey().getLoad();
}
}
return load;
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#pollResponse(String, boolean)}
*/
public LightningResponse pollResults(String sessionId, boolean pollDeltaOnly) {
return dataStore.pollResults(sessionId, pollDeltaOnly);
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#getReport(String)}
*/
public LightningRequestReport getReport(String sessionId) {
LightningRequestReport report = dataStore.getReport(sessionId);
return report;
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#getAuditReports(String)}
*/
public List getAuditReports(String sessionId) {
return dataStore.getAuditReports(sessionId);
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#getLightningStats()}
*/
public SystemStatus getLightningStats(){
SystemStatus status = new SystemStatus();
status.setWorkQueueSize(workQueue.size());
status.setReservationLogSize(reservationResponseLog.size());
status.setLastReservationCleanup(systemConfig.getOldReservationCleanupReminderTimeInMillis());
LightningCoreUtil.getJVMMemory(status);
LightningCoreUtil.getCPUUsage(status);
status.setUpTime(System.currentTimeMillis() - status.getSystemStartTime());
status.setQueueLoadSize(getSubmittedLoad());
status.setReservationLoadSize(getReservedLoad());
status.setAvailableTaskCapacity(systemConfig.getMaxTaskCapacity() - (status.getQueueLoadSize() + status.getReservationLoadSize()));
return status;
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#updateSystemConfig(SystemConfig)}
*/
public SystemConfig updateSystemConfig(SystemConfig sysConfig) throws Exception {
try {
this.systemConfig.updateSystemConfig(sysConfig);
LightningCoreUtil.writeSystemConfigToFileSystem(sysConfig);
log.info("\n SystemConfig updated & persisted to file system: " + this.systemConfig.toString());
} catch (Exception e) {
log.error(e.getMessage());
throw new Exception(e.getMessage());
}
return this.systemConfig;
}
/**
* Get the request to be processed queue.
* @return to process queue
*/
public BlockingQueue getWorkQueue() {
return workQueue;
}
/**
* Set the request to be processed queue.
* @param workQueue to process queue
*/
public void setWorkQueue(BlockingQueue workQueue) {
this.workQueue = workQueue;
}
/* (non-Javadoc)
* @see {@link TaskExecutionService#getSystemConfig()}
*/
public SystemConfig getSystemConfig() {
return this.systemConfig;
}
/**
* Get the current reservation list.
* @return the current reservation list
*/
public Map getReservationResponseLog() {
return reservationResponseLog;
}
}