// Path: client/src/main/java/lt/emasina/esj/model/RequestOperation.java
// public abstract class RequestOperation<F extends Message> extends ResponseOperation {
// 
//     private final TcpConnection connection;
//     protected F request;
// 
//     public RequestOperation(TcpConnection connection, F request) {
//         this.connection = connection;
//         this.request = request;
//     }
// 
//     //private final Semaphore processing = new Semaphore(0);
// 
//     public TcpPackage getRequestPackage() {
//         return request.getTcpPackage(connection.getSettings());
//     }
// 
//     public UUID getCorrelationId() {
//         return request.getCorrelationId();
//     }
// 
//     public void doneProcessing() {
//         //processing.release();
//     }
// 
//     public void send() {
//         sendAsync();
//         /*try {
//             processing.acquire();
//         } catch (InterruptedException ex) {
//             log.warn("Processing was interrpupted", ex);
//         }*/
//     }
// 
//     public void sendAsync() {
//         connection.send(this);
//     }
// 
//     /**
//      * @return the connection
//      */
//     public TcpConnection getConnection() {
//         return connection;
//     }
// 
//     /**
//      * @return the request
//      */
//     public F getRequest() {
//         return request;
//     }
// 
// }
// 
// Path: client/src/main/java/lt/emasina/esj/model/ResponseOperation.java
// public abstract class ResponseOperation {
// 
//     public boolean hasSingleResponse = true;
// 
//     public abstract void setResponsePackage(TcpPackage pckg);
// 
// }
// 
// Path: client/src/main/java/lt/emasina/esj/operation/HeartBeatResponseOperation.java
// public class HeartBeatResponseOperation extends RequestOperation<HeartBeatResponse> {
// 
//     public HeartBeatResponseOperation(TcpConnection connection, UUID correlationId) {
//         super(connection, new HeartBeatResponse());
//         this.getRequest().setCorrelationId(correlationId);
//     }
// 
//     @Override
//     public void setResponsePackage(TcpPackage pckg) {
// 
//     }
// 
// }


import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Semaphore;
import lt.emasina.esj.model.RequestOperation;
import lt.emasina.esj.model.ResponseOperation;
import lt.emasina.esj.operation.HeartBeatResponseOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
                    while (sending.isEmpty() == false) {
                        RequestOperation op = sending.poll();
                        if (op instanceof RequestResponseOperation) {
                            RequestResponseOperation rro = (RequestResponseOperation) op;
                            //rro.onError(new IOException());
                        }
                        op.doneProcessing();
                    }

                    // stop all receiving events
                    log.debug("Is receiving empty: " + receiving.isEmpty());
                    for (Map.Entry<UUID, ResponseOperation> entry : receiving.entrySet()) {
                        ResponseOperation op = entry.getValue();
                        if (op instanceof RequestResponseOperation) {
                            RequestResponseOperation rro = (RequestResponseOperation) op;
                            //rro.onError(new IOException());
                            rro.doneProcessing();
                        }

                    }
                    //receiving.clear();
                    */
                    
                    socket.close();
                } catch (IOException ex) {
                    log.warn("Error while closing socket", ex);
                }

                // Make sure that what was sent but not received would be re-sent
                
// Path: client/src/main/java/lt/emasina/esj/model/RequestOperation.java
// public abstract class RequestOperation<F extends Message> extends ResponseOperation {
// 
//     private final TcpConnection connection;
//     protected F request;
// 
//     public RequestOperation(TcpConnection connection, F request) {
//         this.connection = connection;
//         this.request = request;
//     }
// 
//     //private final Semaphore processing = new Semaphore(0);
// 
//     public TcpPackage getRequestPackage() {
//         return request.getTcpPackage(connection.getSettings());
//     }
// 
//     public UUID getCorrelationId() {
//         return request.getCorrelationId();
//     }
// 
//     public void doneProcessing() {
//         //processing.release();
//     }
// 
//     public void send() {
//         sendAsync();
//         /*try {
//             processing.acquire();
//         } catch (InterruptedException ex) {
//             log.warn("Processing was interrpupted", ex);
//         }*/
//     }
// 
//     public void sendAsync() {
//         connection.send(this);
//     }
// 
//     /**
//      * @return the connection
//      */
//     public TcpConnection getConnection() {
//         return connection;
//     }
// 
//     /**
//      * @return the request
//      */
//     public F getRequest() {
//         return request;
//     }
// 
// }
// 
// Path: client/src/main/java/lt/emasina/esj/model/ResponseOperation.java
// public abstract class ResponseOperation {
// 
//     public boolean hasSingleResponse = true;
// 
//     public abstract void setResponsePackage(TcpPackage pckg);
// 
// }
// 
// Path: client/src/main/java/lt/emasina/esj/operation/HeartBeatResponseOperation.java
// public class HeartBeatResponseOperation extends RequestOperation<HeartBeatResponse> {
// 
//     public HeartBeatResponseOperation(TcpConnection connection, UUID correlationId) {
//         super(connection, new HeartBeatResponse());
//         this.getRequest().setCorrelationId(correlationId);
//     }
// 
//     @Override
//     public void setResponsePackage(TcpPackage pckg) {
// 
//     }
// 
// }


// Path: client/src/main/java/lt/emasina/esj/tcp/TcpSocketManager.java
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Semaphore;
import lt.emasina.esj.model.RequestOperation;
import lt.emasina.esj.model.ResponseOperation;
import lt.emasina.esj.operation.HeartBeatResponseOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

                    while (sending.isEmpty() == false) {
                        RequestOperation op = sending.poll();
                        if (op instanceof RequestResponseOperation) {
                            RequestResponseOperation rro = (RequestResponseOperation) op;
                            //rro.onError(new IOException());
                        }
                        op.doneProcessing();
                    }

                    // stop all receiving events
                    log.debug("Is receiving empty: " + receiving.isEmpty());
                    for (Map.Entry<UUID, ResponseOperation> entry : receiving.entrySet()) {
                        ResponseOperation op = entry.getValue();
                        if (op instanceof RequestResponseOperation) {
                            RequestResponseOperation rro = (RequestResponseOperation) op;
                            //rro.onError(new IOException());
                            rro.doneProcessing();
                        }

                    }
                    //receiving.clear();
                    */
                    
                    socket.close();
                } catch (IOException ex) {
                    log.warn("Error while closing socket", ex);
                }

                // Make sure that what was sent but not received would be re-sent
                
				List<UUID> toRemove = new ArrayList<>();