/**
* Copyright (c) 2011-2014, OpenIoT
*
* This file is part of OpenIoT.
*
* OpenIoT 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, version 3 of the License.
*
* OpenIoT 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 OpenIoT. If not, see <http://www.gnu.org/licenses/>.
*
* Contact: OpenIoT mailto: info@openiot.eu
* @author Timotee Maret
* @author Ali Salehi
*/
package org.openiot.gsn.acquisition2.server;
import org.openiot.gsn.acquisition2.SafeStorage;
import org.openiot.gsn.acquisition2.messages.AcknowledgmentMsg;
import org.openiot.gsn.acquisition2.messages.DataMsg;
import org.openiot.gsn.acquisition2.messages.HelloMsg;
import org.openiot.gsn.acquisition2.wrappers.AbstractWrapper2;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.log4j.Logger;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class SafeStorageServerSessionHandler extends IoHandlerAdapter{
private static final String SESSION_STATE_KEY = "ssk";
private SafeStorage ss;
public SafeStorageServerSessionHandler(SafeStorage ss) throws ClassNotFoundException, SQLException {
this.ss = ss;
}
private static transient Logger logger = Logger.getLogger ( SafeStorageServerSessionHandler.class );
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
session.close();
// Update the number of clients using this wrapper.
}
public void messageReceived(IoSession session, Object message) throws Exception {
if (message instanceof HelloMsg) {
HelloMsg hello = (HelloMsg) message;
logger.debug("Hello received : "+hello.getWrapperDetails().toString());
AbstractWrapper2 wrapper = ss.prepareWrapper(hello, session);
if (wrapper == null) {
//session.close();
return;
}
SessionState sstate = new SessionState () ;
sstate.setWrapper(wrapper);
sstate.setReaderPS(ss.getStorage().createPreparedStatement("select pk,stream_element,created_at from "+wrapper.getTableName()+" where processed = false order by pk asc limit 1"));
logger.debug("isKeepProcessedSafeStorageEntries: " + wrapper.isKeepProcessedSafeStorageEntries());
if (wrapper.isKeepProcessedSafeStorageEntries()) {
sstate.setSuccessAckUpdatePS(ss.getStorage().createPreparedStatement("update "+wrapper.getTableName()+" set PROCESSED = true where pk = ? "));
}
else {
sstate.setSuccessAckUpdatePS(ss.getStorage().createPreparedStatement("delete from " + wrapper.getTableName() + " where pk = ? "));
}
session.setAttribute(SESSION_STATE_KEY, sstate);
}
if (message instanceof AcknowledgmentMsg) {
AcknowledgmentMsg ack = (AcknowledgmentMsg)message;
if (!ack.isAck()) {
logger.error("Recieved Nack for Hello Message sent for "+((HelloMsg) message).getWrapperDetails().toString());
logger.error("Closing the connection to the SafeStorageServer...");
session.close();
return;
}else {
SessionState sstate = (SessionState) session.getAttribute(SESSION_STATE_KEY);
if (sstate != null) {
sstate.getSuccessAckUpdatePS().clearParameters();
sstate.getSuccessAckUpdatePS().setLong(1, ack.getSeqNumber());
sstate.getSuccessAckUpdatePS().executeUpdate();
}
else {
logger.error("No Session State found for session >" + session + "<");
}
}
}
//At this point we've got either HelloMsg or Positive AckMsg
// keep sending new data
postData(session);
}
/**
* Send one (block until one available to be sent).
* @param session
* @throws InterruptedException
*/
private void postData(IoSession session) throws SQLException, InterruptedException{
SessionState sstate = (SessionState) session.getAttribute(SESSION_STATE_KEY);
if (sstate == null) {
logger.error("No Session State found for session >" + session + "<");
return ;
}
ResultSet rs = sstate.getReaderPS().executeQuery();
if (rs.next()) {
long pk =rs.getLong(1);
Object[] se = (Object[]) rs.getArray(2).getArray();
long ts = rs.getTimestamp(3).getTime();
rs.close();
session.write(new DataMsg(se,pk,ts));
logger.debug("Sending data");
}
else {
logger.debug("Blocking for the wrapper's until a new data have generated.");
sstate.getWrapper().canReaderDB();
postData(session);
}
}
public void sessionClosed(IoSession session) throws Exception {
SessionState sstate = (SessionState) session.getAttribute(SESSION_STATE_KEY);
if (sstate == null) {
logger.error("No Session State found for session >" + session + "<");
return ;
}
if (sstate.getReaderPS() != null) sstate.getReaderPS().close();
if (sstate.getSuccessAckUpdatePS() != null) sstate.getSuccessAckUpdatePS().close();
logger.warn("Session >" + session + "< is closed");
// Update the number of clients using this wrapper.
}
public void sessionOpened(IoSession session) throws Exception {
logger.warn("Session >" + session + "< is open");
// Update the number of clients using this wrapper.
}
private class SessionState {
private AbstractWrapper2 wrapper;
private PreparedStatement readerPS = null;
private PreparedStatement successAckUpdatePS;
public SessionState () {}
public AbstractWrapper2 getWrapper() {
return wrapper;
}
public void setWrapper(AbstractWrapper2 wrapper) {
this.wrapper = wrapper;
}
public PreparedStatement getReaderPS() {
return readerPS;
}
public void setReaderPS(PreparedStatement readerPS) {
this.readerPS = readerPS;
}
public PreparedStatement getSuccessAckUpdatePS() {
return successAckUpdatePS;
}
public void setSuccessAckUpdatePS(PreparedStatement successAckUpdatePS) {
this.successAckUpdatePS = successAckUpdatePS;
}
}
}