/*
* 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.Iterator;
import java.util.concurrent.Semaphore;
abstract class AbstractChannel implements Channel
{
/**
* Default channel weight with respects to this channel siblings.
*/
public static int DEFAULT_WEIGHT = 1;
/**
* A semaphore to wait from parent channel releases of buffer quantum.
*/
private final Semaphore semaphore = new Semaphore(0, true);
private final Semaphore pokeSemaphore = new Semaphore(0, true);
/**
* Name (may be null).
*/
private String name = null;
/**
* Weight with respects to this channel siblings.
*/
private int weight = DEFAULT_WEIGHT;
/**
* Parent channel (may be null if detached).
*/
private Channel parent = null;
private UserQuotas defaultUserQuotas;
private int awaitingPermits = 0;
/**
* Default constructor.
*/
AbstractChannel(final String name) throws IllegalArgumentException
{
// Check parameter
if (name == null)
{
throw new IllegalArgumentException(
"A network class shall be created with a non-null name.");
}
// Assign name
this.name = name;
}
/**
* @return channel name (may be null for anonymous).
*/
@Override
public String getName()
{
return this.name;
}
@Override
public String getPath()
{
if (this.getParent() != null)
{
return "" + this.getParent().getPath() + "/" + this.getName();
}
return "/" + this.name;
}
/**
* Define or alter channel name.
*
* @param name is the name of the channel to be defined. May be null.
*/
public void setName(String name)
{
this.name = name;
}
@Override
public int getWeight()
{
return weight;
}
public void setWeight(int weight)
{
this.weight = weight;
}
/**
* @return the parent (may be null if detached).
*/
@Override
public Channel getParent()
{
return parent;
}
/**
* @param parent the parent to set.
*/
@Override
public void setParent(Channel parent)
{
this.parent = parent;
}
protected void setDefaultUserQuotas(final UserQuotas defaults)
{
//TODO Check consequences if changed during runtime
this.defaultUserQuotas = defaults;
}
@Override
public Iterator<Channel> iterator()
{
return new Iterator<Channel>()
{
@Override
public boolean hasNext()
{
return false;
}
@Override
public Channel next()
{
return null;
}
@Override
public void remove()
{
}
};
}
public Channel getChannel(ConnectionParameters parameters)
throws IllegalArgumentException, RegulationException
{
return null;
}
@Override
public UserQuotas getUserQuotas()
{
return getUserQuotas(false);
}
@Override
public UserQuotas getUserQuotas(boolean monotonic)
{
if ((monotonic == true) || (this.defaultUserQuotas != null)
|| (this.getParent() == null))
{
return this.defaultUserQuotas;
}
return this.getParent().getUserQuotas (monotonic);
}
/**
* @throws InterruptedException
*/
@Override
public void acquire(int permits) throws IllegalArgumentException,
RegulationException, InterruptedException
{
if (this.getParent() == null)
{
return;
}
this.awaitingPermits += permits;
// this.getParent().poke();
// Acquire the permits from the attached semaphore
// this.semaphore.acquire(permits);
}
@Override
public void release(int permits)
{
this.semaphore.release(permits);
this.awaitingPermits -= permits;
if (this.awaitingPermits < 0)
{
this.awaitingPermits = 0;
}
}
@Override
public int getAwaitingPermits()
{
return this.awaitingPermits;
}
@Override
public int getAvailablePermits()
{
return this.semaphore.availablePermits();
}
@Override
public void poke()
{
pokeSemaphore.release();
}
void waitPoke() throws InterruptedException
{
pokeSemaphore.acquire();
pokeSemaphore.drainPermits();
}
} // End AbstractChannel class