package hu.ppke.itk.itkStock.nio.threadpool;
import hu.ppke.itk.itkStock.client.watcherClient.SerializationTools;
import hu.ppke.itk.itkStock.server.db.historicData.StockData;
import hu.ppke.itk.itkStock.server.db.historicData.StockDate;
import hu.ppke.itk.itkStock.server.db.historicData.StockTime;
import hu.ppke.itk.itkStock.server.db.historicData.Transaction;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.sql.SQLException;
import java.util.Map;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Andras A simple Thread class to service on the thread pool request.
*/
/**
* @author Andras
*
*/
public class WorkerThread extends Thread {
private SelectionKey key;
private ByteBuffer data;
public synchronized void run() {
System.out.println(this.getName() + " is ready");
while (true) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace(); // Clear interrupt status
WorkerThread.interrupted();
}
try {
writeChannel();
} catch (Exception e) {
System.out.println("Sending historic data to user failed.");
e.printStackTrace();
}
}
}
/**
* This method is called from the static HistoricDataWorker. At every pull
* request, this method sets the serviceable selection key, and generates
* the response asked inside the requested data byte array. Finally, it
* notifyes the run loop, that we got data it can service.
*
* @param k
* - the key to service
* @param requestedData
* - The requested data, in its specific form.
*/
public synchronized void serviceChannel(SelectionKey k, byte[] requestedData) {
key = k;
try {
data = request(requestedData);
} catch (SQLException e) {
e.printStackTrace();
data = ByteBuffer.wrap("There where database error at the request"
.getBytes());
}
key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
this.notify();
}
/**
* @param r
* The data in byte[], in the form of T(optional ticker(s,
* separeted my commas))S(Y-m-d of the given day, in case of the
* next parameter is not empty, this means the first day)E(Y-m-d
* or a simple -)
* Examples:
* T(OTP,EGIS)S(2012-01-01)E(2012-10-10)
* OTP and EGIS datas between 2012-01-01 and 2012-10-10
* T()S(2010-01-25)E(-)
* all data from 2010-01-25
* @return The serialized data.
* @throws SQLException
*/
private synchronized ByteBuffer request(byte[] r) throws SQLException {
Pattern datePatt = Pattern.compile("T\\((.+)\\)S\\((.+)\\)E\\((.+)\\)");
Matcher m = datePatt.matcher(r.toString());
Map<String, SortedMap<StockDate, SortedMap<StockTime, Transaction>>> result = null;
if (m.matches()) {
String[] tickers = m.group(1).split(",");
int year = Integer.parseInt(m.group(2).split("-")[0]);
int month = Integer.parseInt(m.group(2).split("-")[1]);
int day = Integer.parseInt(m.group(2).split("-")[2]);
StockDate start = new StockDate(year, month, day);
StockDate end = null;
String[] temp = m.group(3).split("-");
if (temp.length > 1) {
year = Integer.parseInt(temp[0]);
month = Integer.parseInt(temp[1]);
day = Integer.parseInt(temp[2]);
end = new StockDate(year, month, day);
}
if (tickers[0].isEmpty()) {
if (end == null)
result = StockData.fetchData(start);
else
result = StockData.fetchData(start, end);
} else {
if (end == null)
result = StockData.fetchData(tickers, start);
else
result = StockData.fetchData(tickers, start, end);
}
}
r = SerializationTools.objectToBytes(result);
ByteBuffer buffer = ByteBuffer.allocate(r.length);
buffer.put(r);
return buffer;
}
void writeChannel() throws Exception {
SocketChannel socketChannel = (SocketChannel) key.channel();
socketChannel.write(data);
key.interestOps(SelectionKey.OP_READ);
}
}