fr.gael.dhus.network.ChannelFlow.java Source code

Java tutorial

Introduction

Here is the source code for fr.gael.dhus.network.ChannelFlow.java

Source

/*
 * Data Hub Service (DHuS) - For Space data distribution.
 * Copyright (C) 2013,2014,2015 GAEL Systems
 *
 * This file is part of DHuS software sources.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package fr.gael.dhus.network;

import java.util.Date;

import com.google.common.util.concurrent.RateLimiter;

import fr.gael.dhus.database.object.User;

public class ChannelFlow extends AbstractChannel {
    private final ConnectionParameters parameters;

    private long totalAcquiredPermits = 0L;

    private long maxAllowedPermits = -1L;

    private RateLimiter rateLimiter = null;

    private Date firstPermitDate = null;

    ChannelFlow(final String name, final ConnectionParameters parameters)
            throws IllegalArgumentException, RegulationException {
        // Call top level class constructor
        super(name);

        // Check parameter
        if (parameters == null) {
            throw new IllegalArgumentException("Cannot build a channel flow from a null " + "set of parameters.");
        }

        // Store parameters
        // TODO Check if this should not be a copy to avoid param updates
        this.parameters = parameters;
    }

    @Override
    public int countUserChannels(final User user) throws IllegalArgumentException {
        // Return 1 both users are anonymous
        if ((user == null) && (this.parameters.getUser() == null)) {
            return 1;
        }

        // Return 0 if one of the user names is not available
        if ((user == null) || (user.getUsername() == null) || (this.parameters.getUser() == null)
                || (this.parameters.getUser().getUsername() == null)) {
            return 0;
        }

        // Returns 1 if both user names are equal
        if (user.getUsername().equals(this.parameters.getUser().getUsername())) {
            return 1;
        }

        // Otherwise return 0
        return 0;
    }

    /**
     * @param parent the parent to set.
     */
    @Override
    public void setParent(Channel parent) {
        super.setParent(parent);

        UserQuotas quotas = this.getUserQuotas();

        if (quotas != null) {
            if (quotas.getMaxBandwidth() != null) {
                this.rateLimiter = RateLimiter.create(quotas.getMaxBandwidth().intValue());
            }

            if (quotas.getMaxSize() != null) {
                this.maxAllowedPermits = quotas.getMaxSize().longValue();
            }
        }
    }

    /**
     * Rate limited distribution of permits.
     *
     * @throws IllegalArgumentException if the requested number of permits is
     *            negative or zero
     * @return time spent sleeping to enforce rate, in seconds; 0.0 if not
     *         rate-limited
     * @throws InterruptedException
     */
    @Override
    public void acquire(int permits) throws IllegalArgumentException, RegulationException, InterruptedException {
        // Initialize first permit date if not already done
        if (this.firstPermitDate == null) {
            this.firstPermitDate = new Date();
        }

        // Check quotas
        if ((this.maxAllowedPermits >= 0) && ((this.totalAcquiredPermits + permits) > this.maxAllowedPermits)) {
            // Get user name
            String user_name = "--anonymous--";
            if (parameters.getUser() != null) {
                user_name = parameters.getUser().getUsername();
            }

            // Throw regulation exception
            throw new RegulationException("Maximum size of " + this.maxAllowedPermits
                    + " bytes for a single flow achieved by the user \"" + user_name + "\"");
        }

        // Update total acquired permits
        this.totalAcquiredPermits += permits;

        // Case of bandwidth cap
        if (this.rateLimiter != null) {
            this.rateLimiter.acquire(permits);
        }

        // Acquire from upper channels
        super.acquire(permits);
    }

    /**
     * @return the totalAcquiredPermits
     */
    public long getTransferedSize() {
        return totalAcquiredPermits;
    }

    /**
     * @return the firstPermitDate
     */
    public Date getStartDate() {
        return firstPermitDate;
    }

    @Override
    public String toString() {
        Date current_date = new Date();

        UserQuotas user_quotas = this.getUserQuotas();
        String quotas_message = (user_quotas != null ? user_quotas.toString() : "User Quotas: none");

        String avg_bandwidth = "Average bandwidth: -- undetermined --";

        if (this.firstPermitDate != null) {
            long delay = current_date.getTime() - this.firstPermitDate.getTime();

            if (delay > 0) {
                avg_bandwidth = "Average bandwidth: "
                        + (8000 * this.totalAcquiredPermits
                                / ((current_date.getTime() - this.firstPermitDate.getTime()) * 1048576))
                        + " Mbit/s";
            } else {
                avg_bandwidth = "Average bandwidth: -- transfer delay too small --";
            }
        }

        return "Channel Flow (" + ((this.getName() != null) ? this.getName() : "--anonymous--") + " x "
                + this.getWeight() + ") - " + quotas_message + " - " + avg_bandwidth;
    }
}