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

com.vmware.xenon.common.RoundRobinOperationQueue Maven / Gradle / Ivy

There is a newer version: 1.6.18
Show newest version
/*
 * Copyright (c) 2014-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.xenon.common;

import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Queue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentSkipListMap;

public class RoundRobinOperationQueue {

    public static final int INITIAL_CAPACITY = 256;

    public static RoundRobinOperationQueue create() {
        return new RoundRobinOperationQueue();
    }

    private final NavigableMap> queues = new ConcurrentSkipListMap<>();

    private String activeKey = "";

    private RoundRobinOperationQueue() {

    }

    /**
     * Queue the operation on the queue associated with the key
     */
    public synchronized boolean offer(String key, Operation op) {
        if (key == null || op == null) {
            throw new IllegalArgumentException("key and operation are required");
        }

        Queue q = this.queues.computeIfAbsent(key, (k) -> new ArrayDeque<>(INITIAL_CAPACITY));

        if (!q.offer(op)) {
            op.setStatusCode(Operation.STATUS_CODE_UNAVAILABLE);
            op.fail(new CancellationException("queue limit exceeded"));
            return false;
        }

        return true;
    }

    /**
     * Determines the active queue, and polls it for an operation. If no operation
     * is found the queue is removed from the map of queues and the methods proceeds
     * to check the next queue, until an operation is found.
     * If all queues are empty and no operation was found, the method returns null
     */
    public synchronized Operation poll() {
        while (!this.queues.isEmpty()) {
            Entry> nextActive = this.queues.higherEntry(this.activeKey);
            if (nextActive == null) {
                nextActive = this.queues.firstEntry();
            }
            this.activeKey = nextActive.getKey();
            Operation op = nextActive.getValue().poll();
            if (op != null) {
                return op;
            } else {
                this.queues.remove(nextActive.getKey());
            }
        }

        return null;
    }

    public boolean isEmpty() {
        return this.queues.isEmpty();
    }

    public Map sizesByKey() {
        Map sizes = new HashMap<>();
        synchronized (this) {
            for (Entry> queueEntry : this.queues.entrySet()) {
                sizes.put(queueEntry.getKey(), queueEntry.getValue().size());
            }
        }
        return sizes;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy