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

com.predic8.membrane.core.transport.http2.PriorityTree Maven / Gradle / Ivy

There is a newer version: 5.6.0
Show newest version
/* Copyright 2020 predic8 GmbH, www.predic8.com

   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.predic8.membrane.core.transport.http2;

import com.google.common.collect.Lists;
import com.predic8.membrane.core.transport.http2.frame.Error;
import com.predic8.membrane.core.transport.http2.frame.FatalConnectionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static org.apache.commons.lang3.StringUtils.repeat;

public class PriorityTree {

    private static final Logger log = LoggerFactory.getLogger(PriorityTree.class);

    private StreamInfo root = new StreamInfo(0, null);

    public void reprioritize(@NotNull StreamInfo stream, int weight, @Null StreamInfo parent, boolean exclusive) throws IOException {
        if (parent == stream)
            throw new FatalConnectionException(Error.ERROR_PROTOCOL_ERROR);

        if (parent == null)
            parent = root;

        if (log.isDebugEnabled())
            log.debug("reprioritize(streamId=" + stream.getStreamId() + ", weight=" + weight + ", parentStreamId=" + parent.getStreamId() + ", exclusive=" + exclusive + ")");

        if (isChildOf(parent, stream)) {
            parent.getPriorityParent().getPriorityChildren().remove(parent);
            parent.setPriorityParent(null);

            StreamInfo otherNewParent = stream.getPriorityParent();
            otherNewParent.getPriorityChildren().add(parent);
            parent.setPriorityParent(otherNewParent);
        }

        if (exclusive) {
            for (StreamInfo streamInfo : parent.getPriorityChildren())
                streamInfo.setPriorityParent(stream);
            stream.getPriorityChildren().addAll(parent.getPriorityChildren());
            parent.getPriorityChildren().clear();
        }

        if (stream.getPriorityParent() != null)
            stream.getPriorityParent().getPriorityChildren().remove(stream);

        parent.getPriorityChildren().add(stream);
        stream.setWeight(weight);
        stream.setPriorityParent(parent);

        if (log.isTraceEnabled())
            log.trace("\n" + toString());
    }

    private boolean isChildOf(StreamInfo a, StreamInfo b) {
        StreamInfo p = a;
        while (true) {
            p = p.getPriorityParent();
            if (p == null)
                return false;
            if (p == b)
                return true;
        }
    }

    private static List toStringBuilderList(StreamInfo node) {
        if (node.getPriorityChildren().size() == 0)
            return Lists.newArrayList(toStringBuilder(node));
        List priorityChildren = node.getPriorityChildren();
        List> cols = new ArrayList<>(priorityChildren.size());
        for (StreamInfo streamInfo : priorityChildren)
            cols.add(toStringBuilderList(streamInfo));
        List res = merge(cols);
        res.add(0, fill(toStringBuilder(node), res.get(0).length()));
        return res;
    }

    private static StringBuilder toStringBuilder(StreamInfo node) {
        return new StringBuilder(""+node.getStreamId() + " w" + node.getWeight() + " " + node.getState());
    }

    private static StringBuilder fill(StringBuilder sb, int length) {
        while (sb.length() < length)
            sb.append(' ');
        return sb;
    }

    private static List merge(List> matrix) {
        int row = 0;
        int orig = matrix.get(0).get(0).length();
        while (true) {
            StringBuilder rowSb = null;
            int spacesToInsert = 0;
            for (int col = 0; col < matrix.size(); col++) {
                if (rowSb == null && row < matrix.get(col).size()) {
                    rowSb = matrix.get(col).get(row);

                    rowSb.insert(0, repeat(' ', spacesToInsert));
                    rowSb.append("  ");
                    continue;
                }

                int spaces = (col == 0 ? orig : matrix.get(col).get(0).length()) + 2;

                if (rowSb != null) {
                    if (row < matrix.get(col).size()) {
                        rowSb.append(matrix.get(col).get(row));
                        rowSb.append("  ");
                    } else {
                        rowSb.append(repeat(' ', spaces));
                    }
                }

                spacesToInsert += spaces;
            }
            if (rowSb == null)
                break;

            if (row >= matrix.get(0).size())
                matrix.get(0).add(rowSb);

            row++;
        }
        return matrix.get(0);

    }

    @Override
    public String toString() {
        return String.join("\n", toStringBuilderList(root));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy