/*******************************************************************************
* Copyright 2015 alladin-IT GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package at.alladin.rmbt.client.v2.task;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import at.alladin.rmbt.client.AbstractRMBTTest;
import at.alladin.rmbt.client.RMBTClient;
import at.alladin.rmbt.client.RMBTTestParameter;
/**
*
* @author lb
*
*/
public class QoSControlConnection extends AbstractRMBTTest implements Runnable {
public final static Pattern ID_REGEX_PATTERN = Pattern.compile("\\+ID([\\d]*)");
public final AtomicBoolean isRunning = new AtomicBoolean(true);
public final AtomicBoolean couldNotConnect = new AtomicBoolean(false);
private final ConcurrentHashMap<Integer, ControlConnectionResponseCallbackHolder> requestMap =
new ConcurrentHashMap<Integer, ControlConnectionResponseCallbackHolder>();
private final TreeSet<Integer> concurrencyGroupSet = new TreeSet<Integer>();
protected Socket controlSocket;
/**
*
* @param client
* @param params
* @param threadId
*/
public QoSControlConnection(RMBTClient client, RMBTTestParameter params) {
super(client, params, 1);
}
/**
*
* @param qosTask
* @param command
* @param callback
* @throws IOException
*/
public void sendTaskCommand(AbstractQoSTask qosTask, String command, ControlConnectionResponseCallback callback) throws IOException {
if (callback != null) {
requestMap.put(qosTask.getId(), new ControlConnectionResponseCallbackHolder(command, callback));
}
sendMessage(command + " +ID" + qosTask.getId() + "\n");
}
public void run() {
try {
while (isRunning.get()) {
final String response = reader.readLine();
if (response != null) {
final Matcher m = ID_REGEX_PATTERN.matcher(response);
if (m.find()) {
Integer id = Integer.valueOf(m.group(1));
final ControlConnectionResponseCallbackHolder holder = requestMap.remove(id);
if (holder != null && holder.getCallback() != null) {
Runnable responseRunnable = new Runnable() {
public void run() {
holder.getCallback().onResponse(response, holder.getReqeust());
}
};
RMBTClient.getCommonThreadPool().execute(responseRunnable);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
isRunning.set(false);
if (controlSocket != null && !controlSocket.isClosed()) {
try {
controlSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* @throws Exception
*
*/
public void connect() throws Exception {
isRunning.set(true);
try {
controlSocket = connect(null, InetAddress.getByName(params.getHost()), params.getPort(),
AbstractQoSTask.QOS_SERVER_PROTOCOL_VERSION, "ACCEPT", params.isEncryption(), AbstractQoSTask.CONTROL_CONNECTION_TIMEOUT);
}
catch (Exception e) {
isRunning.set(false);
couldNotConnect.set(true);
throw e;
}
}
/**
* @throws IOException
*
*/
public void close() throws IOException {
sendMessage("QUIT\n");
isRunning.set(false);
controlSocket.close();
}
/**
*
* @return
*/
public TreeSet<Integer> getConcurrencyGroupSet() {
return concurrencyGroupSet;
}
/**
*
* @author lb
*
*/
protected final class ControlConnectionResponseCallbackHolder {
ControlConnectionResponseCallback callback;
String reqeust;
public ControlConnectionResponseCallbackHolder(String request, ControlConnectionResponseCallback callback) {
this.reqeust = request;
this.callback = callback;
}
public ControlConnectionResponseCallback getCallback() {
return callback;
}
public void setCallback(ControlConnectionResponseCallback callback) {
this.callback = callback;
}
public String getReqeust() {
return reqeust;
}
public void setReqeust(String reqeust) {
this.reqeust = reqeust;
}
}
}