/* The Java RTP/I latejoin service, Version 0.1 alpha.
*
* This library provides the functionality of a generic RTP/I latejoin service.
*
* Copyright (C) 2000 Juergen Vogel, Martin Mauve
* University of Mannheim / Germany
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Juergen Vogel
* Martin Mauve
*
* e-mail:
* {vogel,mauve}@informatik.uni-mannheim.de
*
* paper mail:
*
* Juergen Vogel
* Martin Mauve
* University of Mannheim
* Lehrstuhl Praktische Informatik IV
* L15, 16
* 68131 Mannheim
* Germany
*/
package rtpi.services.latejoin;
import rtpi.Rtpi;
import rtpi.RtpiSourceInfo;
import rtpi.RtpiStateQuery;
import rtpi.RtpiState;
import rtpi.RtpiEvent;
import rtpi.RtpiDeltaState;
import rtpi.IllegalValueException;
import java.net.*;
import java.util.Vector;
import java.util.Hashtable;
class LateJoinChannelManager {
private static final boolean debug = false;
private LateJoin lj;
private Rtpi rtpi;
private Rtpi ljRtpi;
private RtpiSourceInfo localParticipant;
private int payloadType;
private Hashtable sequenceNumbers= new Hashtable();
LateJoinChannelManager(LateJoin l, Rtpi r, Rtpi ljR, RtpiSourceInfo ljParticipant, int pt) {
lj = l;
rtpi = r;
ljRtpi =ljR;
localParticipant = ljParticipant;
payloadType=pt;
joinGroup();
}
void leaveGroup() {
MembershipManager mm = lj.getMembershipManager();
if (mm.getState() == MembershipManager.MEMBER) {
ljRtpi.leaveGroup();
mm.setState(MembershipManager.NO_MEMBER);
if (debug) {
System.out.println("LateJoinChannelManager::close - leave late join mulitcast group");
}
} else {
System.err.println("LateJoinChannelManager::close - tried to close once more");
}
}
void joinGroup() {
MembershipManager mm = lj.getMembershipManager();
if (mm.getState() == MembershipManager.NO_MEMBER) {
ljRtpi.joinGroup();
mm.setState(MembershipManager.MEMBER);
if (debug) {
System.out.println("LateJoinChannelManager::join - join late join mulitcast group");
}
} else {
System.err.println("LateJoinChannelManager::join - tried to join once more");
}
}
void transmitStateQuery(RtpiStateQuery query) {
if (lj.getMembershipManager().getState() == MembershipManager.NO_MEMBER) {
System.err.println("LateJoinChannelManager::transmitStateQuery - channel closed");
return;
}
ljRtpi.transmitStateQuery(query);
if (debug)
System.out.println(System.currentTimeMillis() + " LateJoinChannelManager::transmitStateQuery");
}
void receiveStateQuery(RtpiStateQuery query) {
SubcomponentManager sm = lj.getSubcomponentManager();
TimerManager tm = lj.getTimerManager();
long id = query.getSubcomponentID();
if (debug)
System.out.println(System.currentTimeMillis() +
" LateJoinChannelManager::handleStateQuery - " +
"received State Query for Subcomponent with ID " + id);
sm.handleStateQuery(id, query.getParticipantID());
}
void requestSubcomponentState(long id) {
SequenceNumberCounter counter = (SequenceNumberCounter) sequenceNumbers.get(new Long(id));
if (counter == null) {
counter = new SequenceNumberCounter(id);
sequenceNumbers.put(new Long(id), counter);
}
try {
RtpiStateQuery query = new RtpiStateQuery(localParticipant.getParticipantID(),
id,
counter.getNextSequenceNumber(),
payloadType,
2,
System.currentTimeMillis(),
ljRtpi.getCombinedHeaderSize());
transmitStateQuery(query);
} catch (Exception ex) {
System.err.println("LateJoinChannelManager: Could not create and send state query - ignored!");
}
if (debug)
System.out.println("LateJoinChannelManager::requestSubcomponentState - " +
"request Subcomponent with ID " + id);
}
void receiveSubcomponentState(long id) {
SubcomponentManager sm = lj.getSubcomponentManager();
Subcomponent ljSub = sm.getSubcomponent(id);
TimerManager tm = lj.getTimerManager();
if (ljSub == null) { // state was faster than LateJoin.subcomponentAdded()
sm.addRemoteSubcomponent(id);
ljSub = sm.getSubcomponent(id);
ljSub.setState(Subcomponent.COMPLETE);
ljSub.setLastTimeSeenNow();
// we don't know if the application will keep the state - maybe she is not
// interested. assume that she is; if not she will choose the policy
// NOT_INTERESTED, so that we set the subcomp's state to NOT_INTERESTED as well
sm.checkClientState();
return;
}
int policy = ljSub.getPolicy();
ljSub.setLastTimeSeenNow();
if (tm.stateQueryTimerRunning(id)) {
tm.deleteStateQueryTimer(id);
if (debug)
System.out.println("LateJoinChannelManager::receiveSubcomponentState - " +
"received requested Subcomponent with ID " + id);
}
if (policy == LateJoin.NET_CAPACITY) {
sm.deleteNetCapacitySubcomponent(id);
}
if (tm.stateReplyTimerRunning(id)) {
tm.deleteStateReplyTimer(id);
if (debug)
System.out.println("LateJoinChannelManager::receiveSubcomponentState - " +
"delete StateReply-Timer for Subcomponent with ID " + id);
}
if ((policy != LateJoin.NOT_INTERESTED) && (policy != LateJoin.NO_POLICY_YET)) {
// if the application is not interested the state won't be kept !
ljSub.setState(Subcomponent.COMPLETE);
sm.checkClientState();
}
}
void receiveEvent(long id) {
SubcomponentManager sm = lj.getSubcomponentManager();
Subcomponent ljSub = sm.getSubcomponent(id);
TimerManager tm = lj.getTimerManager();
if (ljSub == null) return;
int policy = ljSub.getPolicy();
int state = ljSub.getState();
if ((state == Subcomponent.SUBCOMP_DISCOVERED)
&& !sm.useDefaultPolicy()) return; // no policy yet
if (state == Subcomponent.COMPLETE) return; // nothing to do
if (state == Subcomponent.REQUESTED) return; // query already sent
if (policy == LateJoin.EVENT) { // || policy == NET_CAPACITY
// || state == Subcomponent.FAILED -> now its promising to try again !
tm.setStateQueryTimer(id);
ljSub.setState(Subcomponent.REQUESTED);
}
}
void transmitState(RtpiState state) {
MembershipManager mm = lj.getMembershipManager();
if (mm.getState() == MembershipManager.NO_MEMBER) {
if (debug)
System.out.println("LateJoinChannelManager::transmitState - channel closed, rejoin");
joinGroup();
}
rtpi.transmitState(state);
// remember transmission time
Subcomponent sub = lj.getSubcomponentManager().getSubcomponent(state.getSubcomponentID());
sub.setLastTimeSeenNow();
sub.setAcknowledged(false);
// we have acted as server
mm.incrNbrOfAnsweredQueries();
if (lj.getClientStateManager().getState() == ClientStateManager.CLIENT_COMPLETE) {
TimerManager tm = lj.getTimerManager();
tm.deleteServerTimeoutTimer();
tm.setServerTimeoutTimer();
}
if (debug) {
System.out.println(System.currentTimeMillis() +
" LateJoinChannelManager::transmitState - state for subcomponent " +
state.getSubcomponentID());
}
}
}