/// <exception cref="System.IO.IOException"/>
 internal virtual void AddPeer(Peer peer, Sharpen.Thread t, DataXceiver xceiver)
 {
     lock (this)
     {
         if (closed)
         {
             throw new IOException("Server closed.");
         }
         peers[peer]        = t;
         peersXceiver[peer] = xceiver;
     }
 }
        public virtual void Run()
        {
            Peer peer = null;

            while (datanode.shouldRun && !datanode.shutdownForUpgrade)
            {
                try
                {
                    peer = peerServer.Accept();
                    // Make sure the xceiver count is not exceeded
                    int curXceiverCount = datanode.GetXceiverCount();
                    if (curXceiverCount > maxXceiverCount)
                    {
                        throw new IOException("Xceiver count " + curXceiverCount + " exceeds the limit of concurrent xcievers: "
                                              + maxXceiverCount);
                    }
                    new Daemon(datanode.threadGroup, DataXceiver.Create(peer, datanode, this)).Start(
                        );
                }
                catch (SocketTimeoutException)
                {
                }
                catch (AsynchronousCloseException ace)
                {
                    // wake up to see if should continue to run
                    // another thread closed our listener socket - that's expected during shutdown,
                    // but not in other circumstances
                    if (datanode.shouldRun && !datanode.shutdownForUpgrade)
                    {
                        Log.Warn(datanode.GetDisplayName() + ":DataXceiverServer: ", ace);
                    }
                }
                catch (IOException ie)
                {
                    IOUtils.Cleanup(null, peer);
                    Log.Warn(datanode.GetDisplayName() + ":DataXceiverServer: ", ie);
                }
                catch (OutOfMemoryException ie)
                {
                    IOUtils.Cleanup(null, peer);
                    // DataNode can run out of memory if there is too many transfers.
                    // Log the event, Sleep for 30 seconds, other transfers may complete by
                    // then.
                    Log.Error("DataNode is out of memory. Will retry in 30 seconds.", ie);
                    try
                    {
                        Sharpen.Thread.Sleep(30 * 1000);
                    }
                    catch (Exception)
                    {
                    }
                }
                catch (Exception te)
                {
                    // ignore
                    Log.Error(datanode.GetDisplayName() + ":DataXceiverServer: Exiting due to: ", te);
                    datanode.shouldRun = false;
                }
            }
            // Close the server to stop reception of more requests.
            try
            {
                peerServer.Close();
                closed = true;
            }
            catch (IOException ie)
            {
                Log.Warn(datanode.GetDisplayName() + " :DataXceiverServer: close exception", ie);
            }
            // if in restart prep stage, notify peers before closing them.
            if (datanode.shutdownForUpgrade)
            {
                RestartNotifyPeers();
                // Each thread needs some time to process it. If a thread needs
                // to send an OOB message to the client, but blocked on network for
                // long time, we need to force its termination.
                Log.Info("Shutting down DataXceiverServer before restart");
                // Allow roughly up to 2 seconds.
                for (int i = 0; GetNumPeers() > 0 && i < 10; i++)
                {
                    try
                    {
                        Sharpen.Thread.Sleep(200);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            // ignore
            // Close all peers.
            CloseAllPeers();
        }