package com.tesora.dve.db.mysql.portal.protocol;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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/>.
* #L%
*/
import java.util.IdentityHashMap;
/**
*
*/
public class DownstreamFlowControlSet implements CanFlowControl {
IdentityHashMap<CanFlowControl,CanFlowControl> registeredSet = new IdentityHashMap<>();
IdentityHashMap<CanFlowControl,CanFlowControl> blockedSet = new IdentityHashMap<>();
FlowControl upstreamControl = FlowControl.NOOP;
@Override
public void setUpstreamControl(FlowControl control) {
verifyLegalUpstream(control);
//NOTE: does not pause/upause any previous upstream control.
this.upstreamControl = control;
checkFlowControlState();
}
public void register(CanFlowControl control){
verifyLegalDownstream(control);
boolean alreadyExisted = registeredSet.put(control,control) != null;
if (!alreadyExisted) {
SiteFlowControl handle = new SiteFlowControl(control);
control.setUpstreamControl(handle);
checkFlowControlState();
}
}
public void unregister(CanFlowControl control){
verifyLegalDownstream(control);
if (registeredSet.containsKey(control)) {
control.setUpstreamControl(FlowControl.NOOP);
registeredSet.remove(control); //dupe effort, but control might have called back into us on setUpstreamControl.
blockedSet.remove(control);
checkFlowControlState();
}
}
private void checkFlowControlState(){
if (blockedSet.isEmpty()) {
upstreamControl.resumeSourceStreams();
} else {
upstreamControl.pauseSourceStreams();
}
}
private void verifyLegalDownstream(CanFlowControl control) {
if (control == null)
throw new NullPointerException();
if (control == this)
throw new IllegalArgumentException();
}
private void verifyLegalUpstream(FlowControl control) {
if (control == null)
throw new NullPointerException();
if (control == this)
throw new IllegalArgumentException();
}
private void pauseRequested(CanFlowControl downstream) {
blockedSet.put(downstream,downstream);
checkFlowControlState();
}
private void resumeRequested(CanFlowControl downstream) {
blockedSet.remove(downstream);
checkFlowControlState();
}
private class SiteFlowControl implements FlowControl {
CanFlowControl downstream;
public SiteFlowControl(CanFlowControl downstream) {
this.downstream = downstream;
}
@Override
public void pauseSourceStreams() {
pauseRequested(downstream);
}
@Override
public void resumeSourceStreams() {
resumeRequested(downstream);
}
}
}