/*******************************************************************************
* gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/
* Copyright (C) 2014 SVS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package staticContent.evaluation.simulator.core.networkComponent;
import staticContent.evaluation.simulator.Simulator;
import staticContent.evaluation.simulator.annotations.property.BoolSimulationProperty;
import staticContent.evaluation.simulator.annotations.property.DoubleSimulationProperty;
import staticContent.evaluation.simulator.core.event.ClientEvent;
import staticContent.evaluation.simulator.core.event.DistantProxyEvent;
import staticContent.evaluation.simulator.core.event.Event;
import staticContent.evaluation.simulator.core.event.MixEvent;
import staticContent.evaluation.simulator.core.message.*;
import userGeneratedContent.simulatorPlugIns.pluginRegistry.StatisticsType;
import userGeneratedContent.simulatorPlugIns.plugins.mixSendStyle.MixSendStyleImpl;
import userGeneratedContent.simulatorPlugIns.plugins.mixSendStyle.ReplyReceiver;
import userGeneratedContent.simulatorPlugIns.plugins.outputStrategy.OutputStrategyImpl;
public class Mix extends NetworkNode implements ReplyReceiver {
private boolean isFirstMix;
private boolean isLastMix;
protected Simulator simulator;
@BoolSimulationProperty(key="RECEIVER_SUPPORTS_DUMMY_TRAFFIC",
name="Receiver supports dummy traffic",
inject = "0:RECODING_SCHEME,Recoding Scheme"
)
private boolean RECEIVER_SUPPORTS_DUMMY_TRAFFIC;
private OutputStrategyImpl outputStrategy;
private MixSendStyleImpl mixSendStyle;
@DoubleSimulationProperty(key = "PROCESSING_TIME_FOR_1000_REQUESTS",
name="Processing time for 1000 requests (ms)",
inject = "0:RECODING_SCHEME,Recoding Scheme",
min = 0
)
private static double PROCESSING_TIME_FOR_1000_REQUESTS;
@DoubleSimulationProperty(key = "PROCESSING_TIME_FOR_1000_REPLIES",
name="Processing time for 1000 replies (ms)",
inject = "0:RECODING_SCHEME,Recoding Scheme",
min = 0
)
private static double PROCESSING_TIME_FOR_1000_REPLIES;
private static int requestProcessingTime;
private static int replyProcessingTime;
public Mix(String identifier, Simulator simulator, boolean isFirstMix, boolean isLastMix) {
super(identifier, simulator);
this.isFirstMix = isFirstMix;
this.isLastMix = isLastMix;
this.simulator = simulator;
PROCESSING_TIME_FOR_1000_REQUESTS = Simulator.settings.getPropertyAsDouble("PROCESSING_TIME_FOR_1000_REQUESTS"); // ms
PROCESSING_TIME_FOR_1000_REPLIES = Simulator.settings.getPropertyAsDouble("PROCESSING_TIME_FOR_1000_REPLIES"); // ms
requestProcessingTime = (int)Math.round(PROCESSING_TIME_FOR_1000_REQUESTS / 1000d);
replyProcessingTime = (int)Math.round(PROCESSING_TIME_FOR_1000_REPLIES / 1000d);
RECEIVER_SUPPORTS_DUMMY_TRAFFIC = Simulator.settings.getPropertyAsBoolean("RECEIVER_SUPPORTS_DUMMY_TRAFFIC");
}
public void setOutputStrategy(OutputStrategyImpl outputStrategy) {
this.outputStrategy = outputStrategy;
if (isLastMix)
this.mixSendStyle = outputStrategy.getMixSendStyle();
}
public void putOutRequest(NetworkMessage networkMessage) {
if(!networkMessage.isRequest())
throw new RuntimeException("ERROR: Received reply while expecting request");
if (networkMessage instanceof TransportMessage) {
sendToNextHop(networkMessage, 0, DistantProxyEvent.INCOMING_REQUEST);
} else if (networkMessage instanceof MixMessage) {
if (!isLastMix) {
sendToNextHop(networkMessage, 0, MixEvent.INCOMING_MIX_MESSAGE_OF_TYPE_REQUEST);
} else {
((MixMessage)networkMessage).getOwner().statistics.addValue(Simulator.getNow() - ((MixMessage)networkMessage).getCreationTime(), StatisticsType.AVG_CLIENT_LATENCY_REQUESTMIXMESSAGE);
((MixMessage)networkMessage).getOwner().statistics.addValue(Simulator.getNow() - ((MixMessage)networkMessage).getCreationTime(), StatisticsType.MAX_CLIENT_LATENCY_REQUESTMIXMESSAGE);
((MixMessage)networkMessage).getOwner().statistics.addValue(Simulator.getNow() - ((MixMessage)networkMessage).getCreationTime(), StatisticsType.MIN_CLIENT_LATENCY_REQUESTMIXMESSAGE);
if (RECEIVER_SUPPORTS_DUMMY_TRAFFIC)
sendToNextHop(networkMessage, 0, DistantProxyEvent.INCOMING_REQUEST);
else
for (TransportMessage nmm: ((MixMessage)networkMessage).getTransportMessagesContained())
sendToNextHop(nmm, 0, DistantProxyEvent.INCOMING_REQUEST);
}
} else
throw new RuntimeException("ERROR: unknown message type: " +networkMessage);
}
public void putOutReply(MixMessage mixMessage) {
if(mixMessage.isRequest())
throw new RuntimeException("ERROR: Received request while expecting reply");
if (isFirstMix)
sendToPreviousHop(mixMessage, 0, ClientEvent.REPLY_FROM_MIX);
else
sendToPreviousHop(mixMessage, 0, MixEvent.INCOMING_MIX_MESSAGE_OF_TYPE_REPLY);
}
@Override
public void executeEvent(Event event) {
if (!(event.getEventType() instanceof MixEvent)) {
throw new RuntimeException("ERROR: " +super.getIdentifier() +" received wrong Event: "+event +" "+event.getAttachment());
} else {
switch ((MixEvent)event.getEventType()) {
case INCOMING_MIX_MESSAGE_OF_TYPE_REQUEST:
simulator.scheduleEvent(event.reuse(this, (Simulator.getNow() + getMixRequestProcessingTime()), MixEvent.INCOMING_PROCESSED_REQUEST, event.getAttachment()), this);
break;
case INCOMING_PROCESSED_REQUEST:
outputStrategy.incomingRequest((MixMessage)event.getAttachment());
break;
case INCOMING_MIX_MESSAGE_OF_TYPE_REPLY:
simulator.scheduleEvent(event.reuse(this, (Simulator.getNow() + getMixReplyProcessingTime()), MixEvent.INCOMING_PROCESSED_REPLY, event.getAttachment()), this);
break;
case INCOMING_PROCESSED_REPLY:
outputStrategy.incomingReply((MixMessage)event.getAttachment());
break;
case INCOMING_REPLY_FROM_DISTANT_PROXY:
this.mixSendStyle.incomingDataFromServer((TransportMessage)event.getAttachment());
break;
}
}
}
/**
* @param isFirstMix the isFirstMix to set
*/
public void setFirstMix(boolean isFirstMix) {
this.isFirstMix = isFirstMix;
}
/**
* @param isLastMix the isLastMix to set
*/
public void setLastMix(boolean isLastMix) {
this.isLastMix = isLastMix;
}
/**
* @return the isFirstMix
*/
public boolean isFirstMix() {
return isFirstMix;
}
/**
* @return the isLastMix
*/
public boolean isLastMix() {
return isLastMix;
}
/**
* @return the simulator
*/
public Simulator getSimulator() {
return simulator;
}
/**
* @param simulator the simulator to set
*/
public void setSimulator(Simulator simulator) {
this.simulator = simulator;
}
public int getMixRequestProcessingTime() {
return requestProcessingTime;
}
public int getMixReplyProcessingTime() {
return replyProcessingTime;
}
@Override
public void incomingReply(MixMessage mixMessage) {
outputStrategy.incomingReply(mixMessage);
}
}