예제 #1
0
  /** Internal method. Connect to searchd, send request, get response as DataInputStream. */
  private DataInputStream _DoRequest(int command, int version, ByteArrayOutputStream req) {
    /* connect */
    Socket sock = _Connect();
    if (sock == null) return null;

    /* send request */
    byte[] reqBytes = req.toByteArray();
    try {
      DataOutputStream sockDS = new DataOutputStream(sock.getOutputStream());
      sockDS.writeShort(command);
      sockDS.writeShort(version);
      sockDS.writeInt(reqBytes.length);
      sockDS.write(reqBytes);

    } catch (Exception e) {
      _error = "network error: " + e;
      _connerror = true;
      return null;
    }

    /* get response */
    byte[] response = _GetResponse(sock);
    if (response == null) return null;

    /* spawn that tampon */
    return new DataInputStream(new ByteArrayInputStream(response));
  }
예제 #2
0
  /** Internal method. Connect to searchd and exchange versions. */
  private Socket _Connect() {
    if (_socket != null) return _socket;

    _connerror = false;
    Socket sock = null;
    try {
      sock = new Socket();
      sock.setSoTimeout(_timeout);
      InetSocketAddress addr = new InetSocketAddress(_host, _port);
      sock.connect(addr, _timeout);

      DataInputStream sIn = new DataInputStream(sock.getInputStream());
      int version = sIn.readInt();
      if (version < 1) {
        sock.close();
        _error = "expected searchd protocol version 1+, got version " + version;
        return null;
      }

      DataOutputStream sOut = new DataOutputStream(sock.getOutputStream());
      sOut.writeInt(VER_MAJOR_PROTO);

    } catch (IOException e) {
      _error = "connection to " + _host + ":" + _port + " failed: " + e;
      _connerror = true;

      try {
        if (sock != null) sock.close();
      } catch (IOException e1) {
      }
      return null;
    }

    return sock;
  }
예제 #3
0
  /** Close existing persistent connection. */
  public boolean Close() {
    if (_socket == null) {
      _error = "not connected";
      return false;
    }

    try {
      _socket.close();
    } catch (IOException e) {
    }
    _socket = null;
    return true;
  }
예제 #4
0
  /** Open persistent connection to searchd. */
  public boolean Open() {
    if (_socket != null) {
      _error = "already connected";
      return false;
    }

    Socket sock = _Connect();
    if (sock == null) return false;

    // command, command version = 0, body length = 4, body = 1
    try {
      DataOutputStream sOut = new DataOutputStream(sock.getOutputStream());
      sOut.writeShort(SEARCHD_COMMAND_PERSIST);
      sOut.writeShort(0);
      sOut.writeInt(4);
      sOut.writeInt(1);
    } catch (IOException e) {
      _error = "network error: " + e;
      _connerror = true;
    }

    _socket = sock;
    return true;
  }
예제 #5
0
  /** Internal method. Get and check response packet from searchd. */
  private byte[] _GetResponse(Socket sock) {
    /* connect */
    DataInputStream sIn = null;
    InputStream SockInput = null;
    try {
      SockInput = sock.getInputStream();
      sIn = new DataInputStream(SockInput);

    } catch (IOException e) {
      _error = "getInputStream() failed: " + e;
      return null;
    }

    /* read response */
    byte[] response = null;
    short status = 0, ver = 0;
    int len = 0;
    try {
      /* read status fields */
      status = sIn.readShort();
      ver = sIn.readShort();
      len = sIn.readInt();

      /* read response if non-empty */
      if (len <= 0) {
        _error = "invalid response packet size (len=" + len + ")";
        return null;
      }

      response = new byte[len];
      sIn.readFully(response, 0, len);

      /* check status */
      if (status == SEARCHD_WARNING) {
        DataInputStream in = new DataInputStream(new ByteArrayInputStream(response));

        int iWarnLen = in.readInt();
        _warning = new String(response, 4, iWarnLen);

        System.arraycopy(response, 4 + iWarnLen, response, 0, response.length - 4 - iWarnLen);

      } else if (status == SEARCHD_ERROR) {
        _error = "searchd error: " + new String(response, 4, response.length - 4);
        return null;

      } else if (status == SEARCHD_RETRY) {
        _error = "temporary searchd error: " + new String(response, 4, response.length - 4);
        return null;

      } else if (status != SEARCHD_OK) {
        _error = "searched returned unknown status, code=" + status;
        return null;
      }

    } catch (IOException e) {
      if (len != 0) {
        /* get trace, to provide even more failure details */
        PrintWriter ew = new PrintWriter(new StringWriter());
        e.printStackTrace(ew);
        ew.flush();
        ew.close();
        String sTrace = ew.toString();

        /* build error message */
        _error =
            "failed to read searchd response (status="
                + status
                + ", ver="
                + ver
                + ", len="
                + len
                + ", trace="
                + sTrace
                + ")";
      } else {
        _error = "received zero-sized searchd response (searchd crashed?): " + e.getMessage();
      }
      return null;

    } finally {
      if (_socket == null) {
        try {
          if (sIn != null) sIn.close();
          if (sock != null && !sock.isConnected()) sock.close();
        } catch (IOException e) {
          /* silently ignore close failures; nothing could be done anyway */
        }
      }
    }

    return response;
  }