예제 #1
0
  /**
   * 判断返回的数据是否是当前命令的结束包。 当前全部连接都全部返回以后则表示当前命令完全结束。
   *
   * @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++;
    }
  }
예제 #2
0
  /**
   * 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;
    }
  }