/* * 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; } }