/*
* Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
public class DependencyQueue {
private static final Logger LOG = LoggerFactory.getLogger(DependencyQueue.class);
private static final ThreadFactory threadFact = new ThreadFactoryBuilder().setNameFormat("hwvtep-waiting-job-%d").
build();
private static final ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(threadFact);
private final LinkedBlockingQueue<DependentJob> configWaitQueue = new LinkedBlockingQueue<>(
HwvtepSouthboundConstants.WAITING_QUEUE_CAPACITY);
private final LinkedBlockingQueue<DependentJob> opWaitQueue = new LinkedBlockingQueue<>(
HwvtepSouthboundConstants.WAITING_QUEUE_CAPACITY);
private final HwvtepDeviceInfo deviceInfo;
public DependencyQueue(HwvtepDeviceInfo hwvtepDeviceInfo) {
this.deviceInfo = hwvtepDeviceInfo;
}
/**
* Tries to add the job to the waiting queue
* @param waitingJob The job to be enqueued
* @return true if it is successfully added to the queue
*/
public boolean addToQueue(DependentJob waitingJob) {
boolean addedToQueue;
if (waitingJob instanceof DependentJob.ConfigWaitingJob) {
addedToQueue = configWaitQueue.offer(waitingJob);
} else {
addedToQueue = opWaitQueue.offer(waitingJob);
}
if (addedToQueue) {
LOG.debug("Added the waiting job {} to queue", waitingJob.getKey());
} else {
LOG.error("Failed to add the waiting job to queue {}", waitingJob.getKey());
}
return addedToQueue;
}
/**
* Checks if any config data dependent jobs are ready to be processed and process them
* @param connectionInstance The connection instance
*/
public void processReadyJobsFromConfigQueue(HwvtepConnectionInstance connectionInstance) {
processReadyJobs(connectionInstance, configWaitQueue);
}
/**
* Checks if any operational data dependent jobs are ready to be processed and process them
* @param connectionInstance The connection instance
*/
public void processReadyJobsFromOpQueue(HwvtepConnectionInstance connectionInstance) {
processReadyJobs(connectionInstance, opWaitQueue);
}
private void processReadyJobs(final HwvtepConnectionInstance hwvtepConnectionInstance,
LinkedBlockingQueue<DependentJob> queue) {
final List<DependentJob> readyJobs = getReadyJobs(queue);
if (readyJobs.size() > 0) {
executorService.submit(() -> hwvtepConnectionInstance.transact(new TransactCommand() {
@Override
public void execute(TransactionBuilder transactionBuilder) {
HwvtepOperationalState operationalState = new HwvtepOperationalState(hwvtepConnectionInstance);
for (DependentJob job : readyJobs) {
job.onDependencyResolved(operationalState, transactionBuilder);
}
}
@Override
public void onConfigUpdate(TransactionBuilder transaction, InstanceIdentifier nodeIid,
Identifiable data, InstanceIdentifier key, Object... extraData) {
}
@Override
public void doDeviceTransaction(TransactionBuilder transaction, InstanceIdentifier nodeIid,
Identifiable data, InstanceIdentifier key, Object... extraData) {
}
}));
}
}
private List<DependentJob> getReadyJobs(LinkedBlockingQueue<DependentJob> queue) {
List<DependentJob> readyJobs = new ArrayList<>();
Iterator<DependentJob> jobIterator = queue.iterator();
while(jobIterator.hasNext()) {
DependentJob job = jobIterator.next();
long currentTime = System.currentTimeMillis();
if (job.isExpired(currentTime)) {
jobIterator.remove();
continue;
}
if (job.areDependenciesMet(deviceInfo)) {
jobIterator.remove();
readyJobs.add(job);
}
}
return readyJobs;
}
public static void close() {
executorService.shutdown();
}
public void submit(Runnable runnable) {
executorService.submit(runnable);
}
}