/// <summary> Send the cookie first, then the our port number. If the cookie doesn't match the receiver's cookie,
            /// the receiver will reject the connection and close it.
            /// </summary>
            internal virtual void SendConnectInfo(ConnectInfo info)
            {
                byte[] buf;

                if (sock != null)
                {
                    try
                    {
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("Connection.sendLocaladress",   "b4 serializing...");
                        buf = CompactBinaryFormatter.ToByteBuffer(info, null);
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("Connection.sendLocaladress",   "after serializing...");
                        
                        sock.Send(Version.version_id);

                        // write the length of the buffer
                        byte[] lenBuff;
                        lenBuff = Util.Util.WriteInt32(buf.Length);
                        sock.Send(lenBuff);

                        // and finally write the buffer itself
                        sock.Send(buf);
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("Connection.sendLocaladress",   "after sending...");
                        updateLastAccessed();
                    }
                    catch (System.Exception t)
                    {
                        NCacheLog.Error("exception is " + t);
                        throw t;
                    }
                }
            }
        /// <summary>Try to obtain correct Connection (or create one if not yet existent) </summary>
        protected virtual Connection getConnection(Address dest, Address primaryAddress, bool reEstablishCon, bool isPrimary, bool withFirstNIC,bool connectingFirstTime)
        {
            Connection conn = null;
            System.Net.Sockets.Socket sock;
            Address peer_addr = null;
            try
            {
                if (primaryAddress == null) primaryAddress = dest;
                if (withFirstNIC)
                {
                    if (isPrimary)
                        conn = (Connection)conns_NIC_1[dest];
                    else
                        conn = (Connection)secondayrConns_NIC_1[dest];
                }
                else
                {
                    if (isPrimary)
                        conn = (Connection)conns_NIC_2[primaryAddress];
                    else
                        conn = (Connection)secondayrConns_NIC_2[primaryAddress];
                }

                if ((conn == null ||!connectingFirstTime) && reEstablishCon)
                {

                    try
                    {
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection()",   "No Connetion was found found with " + dest.ToString());
                        if (local_addr == null) return null; //cluster being stopped.

                        sock = Connect(dest, withFirstNIC);
                       

                        conn = new Connection(this, sock, primaryAddress, this.NCacheLog, isPrimary, nagglingSize, _retries, _retryInterval);
                        conn.MemManager = MemManager;
                        conn.IamInitiater = true;
                        ConnectInfo conInfo = null;
                        try
                        {
                            byte connectStatus = connectingFirstTime ? ConnectInfo.CONNECT_FIRST_TIME : ConnectInfo.RECONNECTING;
                            
                            conn.sendLocalAddress(local_addr,connectingFirstTime);
                            conn.readPeerAddress(sock,ref peer_addr);
                            if (((Address)local_addr).CompareTo((Address)dest) > 0)
                            {
                                conInfo = new ConnectInfo(connectStatus, GetConnectionId());
                                if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection",   dest + " I should send connect_info");
                                conn.SendConnectInfo(conInfo);
                            }
                            else
                            {
                                conInfo = conn.ReadConnectInfo(sock);
                            }
                            //log.Error("ConnectionTable.getConnection",   " conn_info :" + conInfo);
                            conn.ConInfo = conInfo;
                        }
                        catch (System.Exception e)
                        {
                            NCacheLog.Error("ConnectionTable.getConnection()",   e.Message);
                            conn.DestroySilent();
                            return null;
                        }
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection",   "b4 lock conns.SyncRoot");
                        try
                        {
                            conn_syn_lock.AcquireWriterLock(Timeout.Infinite);
                            if (isPrimary)
                            {
                                if (withFirstNIC)
                                {
                                    if (conns_NIC_1.ContainsKey(dest))
                                    {
                                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection()",   "connection is already in the table");
                                        Connection tmpConn = (Connection)conns_NIC_1[dest];
                                        
                                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection",   "table_con id :" + tmpConn.ConInfo.Id + " new_con id :" + conn.ConInfo.Id);
                                        if (conn.ConInfo.Id < tmpConn.ConInfo.Id)
                                        {
                                            conn.Destroy();
                                            return tmpConn;
                                        }
                                        else
                                        {
                                            if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection()",   dest + "--->connection present in the table is terminated");
                                            
                                            tmpConn.Destroy();
                                             conns_NIC_1.Remove(dest);
                                         }
                                    }

                                    notifyConnectionOpened(dest);
                                }
                                else
                                {
                                    if (conns_NIC_2.ContainsKey(primaryAddress))
                                    {
                                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection()",   "connection is already in the table");
                                        Connection tmpConn = (Connection)conns_NIC_1[dest];
                                        
                                        if (conn.ConInfo.Id < tmpConn.ConInfo.Id)
                                        {
                                            conn.Destroy();
                                            return tmpConn;
                                        }
                                        else
                                        {
                                            NCacheLog.Warn("ConnectionTable.getConnection()",   dest + "connection present in the table is terminated");
                                            
                                            tmpConn.Destroy();
                                            conns_NIC_2.Remove(primaryAddress);
                                        }
                                    }
                                }
                            }
                            addConnection(primaryAddress, conn, isPrimary, withFirstNIC);
                            if (useDedicatedSender) AddDedicatedMessageSender(primaryAddress, conn, withFirstNIC);
                            conn.init();
                        }
                        finally
                        {
                            conn_syn_lock.ReleaseWriterLock();
                        }
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection",   "after lock conns.SyncRoot");
                        
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.getConnection()",   "connection is now working");
                    }
                    finally
                    {

                    }

                }
            }
            catch (System.Threading.ThreadAbortException e)
            {
                
                if (conn != null) conn.Destroy();
                conn = null;
            }
            catch (System.Threading.ThreadInterruptedException ex)
            {
                
                if (conn != null) conn.Destroy();
                conn = null;
            }
            finally
            {
            }
            return conn;
        }
        /// <summary> Acceptor thread. Continuously accept new connections. Create a new thread for each new
        /// connection and put it in conns. When the thread should stop, it is
        /// interrupted by the thread creator.
        /// </summary>
        public virtual void Run(Object arg)
        {
            Object[] objArr = arg as object[];
            TcpListener listener = objArr[0] as TcpListener;
            bool isPrimaryListener = (bool)objArr[1];

            System.Net.Sockets.Socket client_sock;
            Connection conn = null;
            Address peer_addr = null;

            while (listener != null)
            {
                try
                {
                    client_sock = listener.AcceptSocket();
                    int cport = ((IPEndPoint)client_sock.RemoteEndPoint).Port;

                     if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.Run()", "CONNECTION ACCPETED Remote port = " + cport);
                    client_sock.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1);
                    
                    client_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, send_buf_size);
                    client_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, recv_buf_size);

                    object size = client_sock.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
                    size = client_sock.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
                    // create new thread and add to conn table

                    conn = new Connection(this, client_sock, null, _ncacheLog, true, nagglingSize, _retries, _retryInterval); // will call receive(msg)

                    // get peer's address
                    bool connectingFirstTime = conn.readPeerAddress(client_sock, ref peer_addr);
                    conn.sendLocalAddress(local_addr,connectingFirstTime);
                    ConnectInfo conInfo = null;
                    if (((Address)local_addr).CompareTo((Address)peer_addr) > 0)
                    {
                        conInfo = new ConnectInfo(ConnectInfo.CONNECT_FIRST_TIME, GetConnectionId());
                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.Run", peer_addr + " I should send connect_info");

                       
                        conn.SendConnectInfo(conInfo);
                    }
                    else
                    {
                        conInfo = conn.ReadConnectInfo(client_sock);
                        
                    }

                    conn.ConInfo = conInfo;
                    conn.ConInfo.ConnectStatus = connectingFirstTime ? ConnectInfo.CONNECT_FIRST_TIME : ConnectInfo.RECONNECTING;

                    if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.Run()", "Read peer address " + peer_addr.ToString() + "at port" + cport);

                    conn.PeerAddress = peer_addr;

                    if (conInfo.ConnectStatus == ConnectInfo.RECONNECTING)
                    {
                        //if other node is reconnecting then we should check for its member ship first.
                        bool ismember = enclosingInstance.IsMember(peer_addr);
                        if (!ismember)
                        {

                            NCacheLog.CriticalInfo("ConnectionTa ble.Run", "ConnectionTable.Run" + peer_addr + " has connected. but it is no more part of the membership");

                            conn.SendLeaveNotification();
                            Thread.Sleep(1000); //just to make sure that peer node receives the leave notification.
                            conn.Destroy();
                            continue;
                        }
                    }

                    bool isPrimary = true;

                    if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.run", "b4 lock conns.SyncRoot");
                    try
                    {
                        conn_syn_lock.AcquireWriterLock(Timeout.Infinite);

                        if (isPrimaryListener)
                        {

                           if (conns_NIC_1.ContainsKey(peer_addr))
                            {

                                if (!secondayrConns_NIC_1.Contains(peer_addr) && useDualConnection)
                                {
                                    secondayrConns_NIC_1[peer_addr] = conn;
                                    isPrimary = false;
                                }
                                else
                                {

                                
                                    Connection tmpConn = (Connection)conns_NIC_1[peer_addr];

                                    if (conn.ConInfo.Id < tmpConn.ConInfo.Id && conn.ConInfo.ConnectStatus != ConnectInfo.CONNECT_FIRST_TIME)

                                    {

                                        NCacheLog.CriticalInfo("ConnectionTable.Run", "1. Destroying Connection (conn.ConInfo.Id < tmpConn.ConInfo.Id)" + conn.ConInfo.Id.ToString() + ":" + tmpConn.ConInfo.Id.ToString() + conn.ToString());

                                        conn.Destroy();
                                        continue;
                                    }
                                    else
                                    {
                                        if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.Run()", "-->connection present in the talble is terminated");
                                        
                                        tmpConn.Destroy();
                                        conns_NIC_1.Remove(peer_addr);
                                    }

                                }

                            }
                            
                        }

                        else
                        {
                            if (conns_NIC_2.ContainsKey(peer_addr))
                            {
                                if (!secondayrConns_NIC_2.Contains(peer_addr) && useDualConnection)
                                {
                                    secondayrConns_NIC_2[peer_addr] = conn;
                                    isPrimary = false;
                                }
                                else
                                {
                                    if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.Run()", "connection alrady exists in the table");
                                    Connection tmpConn = (Connection)conns_NIC_2[peer_addr];

                                  
                                    if (conn.ConInfo.Id < tmpConn.ConInfo.Id)
                                    {
                                        conn.Destroy();
                                        continue;
                                    }
                                    else
                                    {
                                        NCacheLog.Error("ConnectionTable.Run()", "connection present in the talble is terminated");
                                        tmpConn.Destroy();
                                        conns_NIC_2.Remove(peer_addr);
                                    }
                                }
                            }
                        }
                        conn.IsPrimary = isPrimary;
                        addConnection(peer_addr, conn, isPrimary, isPrimaryListener);

                        conn.MemManager = memManager;

                        if (useDedicatedSender) AddDedicatedMessageSender(conn.peer_addr, conn, isPrimaryListener);

                        conn.init(); 
                    }
                    finally
                    {
                        conn_syn_lock.ReleaseWriterLock();
                    }
                    if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.run", "after lock conns.SyncRoot");

                    if (isPrimary && isPrimaryListener)

                        notifyConnectionOpened(peer_addr);



                    if (NCacheLog.IsInfoEnabled) NCacheLog.Info("ConnectionTable.Run()", "connection working now");
                }
                catch (ExtSocketException sock_ex)
                {
                    NCacheLog.Error("ConnectionTable.Run", "exception is " + sock_ex);

                    if (conn != null)
                        conn.DestroySilent();
                    if (srv_sock1 == null)
                        break; // socket was closed, therefore stop
                }
                catch (System.Exception ex)
                {
                    NCacheLog.Error("ConnectionTable.Run", "exception is " + ex);

                    if (srv_sock1 == null)
                        break; // socket was closed, therefore stop

                }
                finally
                {

                }
            }
        }