/** * 判断返回的数据是否是当前命令的结束包。 当前全部连接都全部返回以后则表示当前命令完全结束。 * * @param conn * @param buffer * @return */ protected CommandStatus checkResponseCompleted(Connection conn, byte[] buffer) { boolean isCompleted = false; ConnectionStatuts connStatus = connStatusMap.get(conn); if (connStatus == null) { CommandMessageHandler.logger.error( "connection Status not Found, byffer=" + StringUtil.dumpAsHex(buffer, buffer.length)); } try { connStatus.buffers.add(buffer); isCompleted = connStatus.isCompleted(buffer); /** * 如果是多个连接的,需要将数据缓存起来,等待命令全部完成以后,将数据进行组装,然后发送到客户端 {@link * #CommandMessageHandler.mergeMessageToClient} */ if (isCompleted) { // set last insert id to client connection; if (conn != source) { if (connStatus.packetIndex == 0 && MysqlPacketBuffer.isOkPacket(buffer)) { if (statment instanceof InsertStatement && currentCommand.isMain()) { OkPacket packet = new OkPacket(); packet.init(buffer, conn); if (packet.insertId > 0) { source.setLastInsertId(packet.insertId); } } } } boolean isAllCompleted = currentCommand.getCompletedCount().incrementAndGet() == connStatusMap.size(); if (isAllCompleted) { connStatus.isMerged = true; } if (isAllCompleted) { if (CommandMessageHandler.logger.isDebugEnabled()) { Packet packet = null; if (MysqlPacketBuffer.isErrorPacket(buffer)) { packet = new ErrorPacket(); } else if (MysqlPacketBuffer.isEofPacket(buffer)) { packet = new EOFPacket(); } else if (MysqlPacketBuffer.isOkPacket(buffer)) { packet = new OkPacket(); } packet.init(buffer, conn); CommandMessageHandler.logger.debug("returned Packet:" + packet); } return CommandStatus.AllCompleted; } else { return CommandStatus.ConnectionCompleted; } } else { return CommandStatus.ConnectionNotComplete; } } finally { connStatus.packetIndex++; } }
/** * Reads a packet from the provided channel, appending to any partially read packet. If the entire * packet data is not yet available, <code>readPacket</code> will return false, otherwise true. * * <p><em>Note:</em> when this method returns true, it is required that the caller read * <em>all</em> of the packet data from the stream before again calling {@link #readPacket} as the * previous packet's data will be elimitated upon the subsequent call. * * @return byte[] if the entire packet has been read, null if the buffer contains only a partial * packet. */ public byte[] readPacket(ReadableByteChannel source) throws IOException { if (checkForCompletePacket()) { calculateAverage(this._length); return readPacket(); } // read whatever data we can from the source do { int got = source.read(_buffer); if (got == -1) { throw new EOFException(); } if (got == 0 && _buffer.hasRemaining()) { return null; } _have += got; if (_length == -1) { // if we didn't already have our length, see if we now // have enough data to obtain it _length = decodeLength(); } if (_length < -1) { _buffer.flip(); byte[] bts = _buffer.array(); throw new IOException( "decodeLength error:_length=" + _length + "\r\n" + StringUtil.dumpAsHex(bts, bts.length)); } // if there's room remaining in the buffer, that means we've // read all there is to read, so we can move on to inspecting // what we've got if (_buffer.remaining() > 0) { break; } // additionally, if the buffer happened to be exactly as long // as we needed, we need to break as well if ((_length > 0) && (_have >= _length)) { break; } // otherwise, we've filled up our buffer as a result of this // read, expand it and try reading some more int newSize = _buffer.capacity() << 1; newSize = newSize > _length ? newSize : _length + 16; if (newSize > MAX_BUFFER_CAPACITY || _buffer.capacity() > 2 * MAX_BUFFER_CAPACITY) { throw new IOException("packet over MAX_BUFFER_CAPACITY size=" + newSize); } ByteBuffer newbuf = ByteBuffer.allocate(newSize); newbuf.put((ByteBuffer) _buffer.flip()); _buffer = newbuf; // don't let things grow without bounds } while (_buffer.capacity() < 2 * MAX_BUFFER_CAPACITY); if (checkForCompletePacket()) { calculateAverage(this._length); return readPacket(); } else { return null; } }