/***************************************************************************
* Copyright (c) 2012-2015 VMware, Inc. 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.
***************************************************************************/
package com.vmware.aurora.util.worker;
import com.vmware.aurora.util.AuAssert;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* CmsWorker manages a pool of threads, each accepting requests with different execution
* requirements and execute them in order of priority and schedule.
*
* As each collection of queues is backed by a single thread,
* all requests are executed sequentially.
*/
@Component
@Scope("singleton")
public class CmsWorker {
static Logger logger = Logger.getLogger(CmsWorker.class);
/**
* An enumeration of all queues of requests to be executed by {\link WorkerThread}s.
*/
public enum WorkQueue {
// No delay VC query queue.
VC_QUERY_NO_DELAY("vcQueryExec"),
// Highest priority queue, execution without delay & threshold (limit capacity).
VC_CACHE_NO_DELAY("vcCacheExec"),
// No delay VC task queue.
VC_TASK_NO_DELAY("vcTaskExec"),
// Execute every 10 seconds, up to 1000 requests per interval.
//VC_QUERY_TEN_SEC_DELAY(new DelayedReqQueue(10, 1000, Integer.MAX_VALUE)),
// Highest priority queue, execution without delay & threshold (limit capacity).
//VC_SYNC_NO_DELAY(new DelayedReqQueue(0, 1000, Integer.MAX_VALUE)),
// Execute every 10 seconds, up to 1000 requests per interval.
//VC_SYNC_TEN_SEC_DELAY(new DelayedReqQueue(10, 1000, Integer.MAX_VALUE)),
// Execute every 1 minute, up to 10 requests per interval.
//VC_SYNC_ONE_MIN_DELAY(new DelayedReqQueue(60, 10, Integer.MAX_VALUE)),
// Execute every 5 minutes, up to 1000 requests per interval.
//VC_CACHE_FIVE_MIN_DELAY(new DelayedReqQueue(5 * 60, 1000, Integer.MAX_VALUE)),
// Execute every 10 seconds, up to 100 requests per interval.
//VC_TASK_TEN_SEC_DELAY(new DelayedReqQueue(10, 100, Integer.MAX_VALUE)),
// Execute every 2 minutes, up to 100 requests per interval.
VC_CACHE_TWO_MIN_DELAY("vcCacheScheduler"),
// Execute every 5 minute, up to 100 requests per interval.
VC_TASK_FIVE_MIN_DELAY("vcCacheScheduler");
// Execute every 1 hour, up to 10 requests per interval.
//VC_TASK_ONE_HOUR_DELAY(new DelayedReqQueue(60 * 60, 10, Integer.MAX_VALUE)),
// Highest priority queue, execution without delay & threshold (limit capacity).
//VCD_SYNC_NO_DELAY(new DelayedReqQueue(0, 1000, Integer.MAX_VALUE)),
// Execute every 10 minutes, up to 1000 requests per interval.
//VCD_SYNC_TEN_MIN_DELAY(new DelayedReqQueue(10 * 60, 1000, Integer.MAX_VALUE)),
// Highest priority queue, execution without delay & threshold (limit capacity).
//BASE_VM_SYNC_NO_DELAY(new DelayedReqQueue(0, 1000, Integer.MAX_VALUE)),
// Execute every 5 minutes, up to 1000 requests per interval.
//BASE_VM_FIVE_MIN_DELAY(new DelayedReqQueue(5 * 60, 1000, Integer.MAX_VALUE)),
// Execute every 5 minute, up to 1000 requests per interval.
//CUSTOM_FIVE_MIN_SYNC_DELAY(new DelayedReqQueue(5 * 60, 1000, 1000)),
//CUSTOM_SYNC_NO_DELAY(new DelayedReqQueue(0, 1000, 1000));
private String executorName;
WorkQueue(String executorName1) {
executorName = executorName1;
}
public String getExecutorName() {
return executorName;
}
}
@Autowired
private Map<String, Executor> executors;
@Autowired
private Map<String, ScheduledExecutorService> schedulers;
private volatile static CmsWorker SINGLETON;
@PostConstruct
public void init() {
SINGLETON = this;
}
@Bean
public static CmsWorker getInstance() {
return SINGLETON;
}
private Executor findExecutor(WorkQueue queue) {
return find(executors, queue);
}
private ScheduledExecutorService findScheduler(WorkQueue queue) {
return find(schedulers, queue);
}
private static<T> T find(Map<String, T> items, WorkQueue name) {
T item = items.get(name.getExecutorName());
AuAssert.check(item != null, "can't find executor/scheduler for: " + name);
return item;
}
public void execRequest(WorkQueue queue, Request req) {
findExecutor(queue).execute(req);
}
public void scheduleRequest(WorkQueue queue, PeriodicRequest req) {
findScheduler(queue).scheduleWithFixedDelay(req, 0, req.getDelay(), TimeUnit.MILLISECONDS);
}
/**
* Add a request to the specified queue.
* @param queue
* @param req
*/
public static void addRequest(WorkQueue queue, Request req) {
SINGLETON.execRequest(queue, req);
}
/**
* Add a periodic request to the specified queue.
* @param req
*/
static public void addPeriodic(PeriodicRequest req) {
SINGLETON.scheduleRequest(req.getQueue(), req);
}
}