@Override public void run() { threadCnt.incrementAndGet(); try { while (running && !shutdown && sock != null) { /** Reads the first int to determine the length of the message */ int length = din.readInt(); if (length <= 0 || length > PACKETMAXSIZE) { throw new IOException("Received packet with invalid packet: " + length); } /** Allocates a new ByteBuffer to receive the message */ byte[] msgArray = new byte[length]; din.readFully(msgArray, 0, length); ByteBuffer message = ByteBuffer.wrap(msgArray); addToRecvQueue(new Message(message.duplicate(), sid)); } } catch (Exception e) { LOG.warn("Connection broken for id " + sid + ", my id = " + self.getId() + ", error = ", e); } finally { LOG.warn("Interrupting SendWorker"); sw.finish(); if (sock != null) { closeSocket(sock); } } }
/** * If this server has initiated the connection, then it gives up on the connection if it loses * challenge. Otherwise, it keeps the connection. */ public boolean initiateConnection(Socket sock, Long sid) { DataOutputStream dout = null; try { // Sending id and challenge dout = new DataOutputStream(sock.getOutputStream()); dout.writeLong(self.getId()); dout.flush(); } catch (IOException e) { LOG.warn("Ignoring exception reading or writing challenge: ", e); closeSocket(sock); return false; } // If lost the challenge, then drop the new connection if (sid > self.getId()) { LOG.info( "Have smaller server identifier, so dropping the " + "connection: (" + sid + ", " + self.getId() + ")"); closeSocket(sock); // Otherwise proceed with the connection } else { SendWorker sw = new SendWorker(sock, sid); RecvWorker rw = new RecvWorker(sock, sid, sw); sw.setRecv(rw); SendWorker vsw = senderWorkerMap.get(sid); if (vsw != null) vsw.finish(); senderWorkerMap.put(sid, sw); if (!queueSendMap.containsKey(sid)) { queueSendMap.put(sid, new ArrayBlockingQueue<ByteBuffer>(SEND_CAPACITY)); } sw.start(); rw.start(); return true; } return false; }
/** * Starts a Thread to start sending outstanding error reports. * * @param onlySendSilentReports If true then only send silent reports. * @param approveReportsFirst If true then approve unapproved reports first. * @return SendWorker that will be sending the report.s */ SendWorker startSendingReports(boolean onlySendSilentReports, boolean approveReportsFirst) { final SendWorker worker = new SendWorker(mContext, mReportSenders, onlySendSilentReports, approveReportsFirst); worker.start(); return worker; }
/** A soft halt simply finishes workers. */ public void softHalt() { for (SendWorker sw : senderWorkerMap.values()) { LOG.debug("Halting sender: " + sw); sw.finish(); } }
/** * If this server receives a connection request, then it gives up on the new connection if it * wins. Notice that it checks whether it has a connection to this server already or not. If it * does, then it sends the smallest possible long value to lose the challenge. */ public boolean receiveConnection(Socket sock) { Long sid = null; try { // Read server id DataInputStream din = new DataInputStream(sock.getInputStream()); sid = din.readLong(); if (sid == QuorumPeer.OBSERVER_ID) { /* * Choose identifier at random. We need a value to identify * the connection. */ sid = observerCounter--; LOG.info("Setting arbitrary identifier to observer: " + sid); } } catch (IOException e) { closeSocket(sock); LOG.warn("Exception reading or writing challenge: " + e.toString()); return false; } // If wins the challenge, then close the new connection. if (sid < self.getId()) { /* * This replica might still believe that the connection to sid is * up, so we have to shut down the workers before trying to open a * new connection. */ SendWorker sw = senderWorkerMap.get(sid); if (sw != null) { sw.finish(); } /* * Now we start a new connection */ LOG.debug("Create new connection to server: " + sid); closeSocket(sock); connectOne(sid); // Otherwise start worker threads to receive data. } else { SendWorker sw = new SendWorker(sock, sid); RecvWorker rw = new RecvWorker(sock, sid, sw); sw.setRecv(rw); SendWorker vsw = senderWorkerMap.get(sid); if (vsw != null) vsw.finish(); senderWorkerMap.put(sid, sw); if (!queueSendMap.containsKey(sid)) { queueSendMap.put(sid, new ArrayBlockingQueue<ByteBuffer>(SEND_CAPACITY)); } sw.start(); rw.start(); return true; } return false; }
/* * 读取对方的sid */ public boolean receiveConnection(Socket sock) { Long sid = null; try { // Read server id DataInputStream din = new DataInputStream(sock.getInputStream()); sid = din.readLong(); if (sid < 0) { // this is not a server id but a protocol version // (see ZOOKEEPER-1633) sid = din.readLong(); // next comes the #bytes in the remainder of the message int num_remaining_bytes = din.readInt(); byte[] b = new byte[num_remaining_bytes]; // remove the remainder of the message from din int num_read = din.read(b); if (num_read != num_remaining_bytes) { LOG.error( "Read only " + num_read + " bytes out of " + num_remaining_bytes + " sent by server " + sid); } } if (sid == QuorumPeer.OBSERVER_ID) { /* * Choose identifier at random. We need a value to identify the * connection. */ sid = observerCounter--; LOG.info("Setting arbitrary identifier to observer: " + sid); } } catch (IOException e) { closeSocket(sock); LOG.warn("Exception reading or writing challenge: " + e.toString()); return false; } // If wins the challenge, then close the new connection. /* * 只允许sid大的连接小的 */ if (sid < self.getId()) { /* * This replica might still believe that the connection to sid is * up, so we have to shut down the workers be fore trying to open a * new connection. */ SendWorker sw = senderWorkerMap.get(sid); if (sw != null) { sw.finish(); } /* * Now we start a new connection */ LOG.debug("Create new connection to server: " + sid); closeSocket(sock); connectOne(sid); // Otherwise start worker threads to receive data. } else { SendWorker sw = new SendWorker(sock, sid); RecvWorker rw = new RecvWorker(sock, sid, sw); sw.setRecv(rw); SendWorker vsw = senderWorkerMap.get(sid); if (vsw != null) vsw.finish(); senderWorkerMap.put(sid, sw); if (!queueSendMap.containsKey(sid)) { queueSendMap.put(sid, new ArrayBlockingQueue<ByteBuffer>(SEND_CAPACITY)); } sw.start(); rw.start(); return true; } return false; }