if (_draining > 0)
{
Iterator<Receiver> itr = _credited.iterator();
while (itr.hasNext())
{
Receiver link = (Receiver) itr.next();
if (link.getDrain())
{
if (!link.draining())
{
// drain completed for this link
int drained = link.drained();
assert(_distributed >= drained);
_distributed -= drained;
_credit += drained;
link.setDrain(false);
_draining--;
itr.remove();
_blocked.add(link);
}
}
}
}
// distribute available credit to blocked links
final int batch = perLinkCredit();
while (_credit > 0 && !_blocked.isEmpty())
{
Receiver link = _blocked.get(0);
_blocked.remove(0);
final int more = Math.min(_credit, batch);
_distributed += more;
_credit -= more;
link.flow(more);
_credited.add(link);
// flow changed, must process it
ConnectionContext ctx = (ConnectionContext) link.getSession().getConnection().getContext();
try
{
ctx.getConnector().process();
} catch (IOException e) {
_logger.log(Level.SEVERE, "Error processing connection", e);
}
}
if (_blocked.isEmpty())
{
_next_drain = 0;
}
else
{
// not enough credit for all links - start draining granted credit
if (_draining == 0)
{
// don't do it too often - pace ourselves (it's expensive)
if (_next_drain == 0)
{
_next_drain = System.currentTimeMillis() + 250;
}
else if (_next_drain <= System.currentTimeMillis())
{
// initiate drain, free up at most enough to satisfy blocked
_next_drain = 0;
int needed = _blocked.size() * batch;
for (Receiver link : _credited)
{
if (!link.getDrain()) {
link.setDrain(true);
needed -= link.getRemoteCredit();
_draining++;
// drain requested on link, must process it
ConnectionContext ctx = (ConnectionContext) link.getSession().getConnection().getContext();
try
{
ctx.getConnector().process();
} catch (IOException e) {
_logger.log(Level.SEVERE, "Error processing connection", e);