Example #1
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;
  }
Example #2
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));
  }
Example #3
0
  /** Internal method. String IO helper. */
  private static void writeNetUTF8(DataOutputStream ostream, String str) throws IOException {
    if (str == null) {
      ostream.writeInt(0);
      return;
    }

    byte[] sBytes = str.getBytes("UTF-8");
    int iLen = sBytes.length;

    ostream.writeInt(iLen);
    ostream.write(sBytes);
  }
Example #4
0
 /**
  * Set float range filter. Only match records if attribute value is beetwen min and max
  * (inclusive).
  */
 public void SetFilterFloatRange(String attribute, float min, float max, boolean exclude)
     throws SphinxException {
   myAssert(min <= max, "min must be less or equal to max");
   try {
     writeNetUTF8(_filters, attribute);
     _filters.writeInt(SPH_FILTER_FLOATRANGE);
     _filters.writeFloat(min);
     _filters.writeFloat(max);
     _filters.writeInt(exclude ? 1 : 0);
   } catch (Exception e) {
     myAssert(false, "IOException: " + e.getMessage());
   }
   _filterCount++;
 }
Example #5
0
  /**
   * Connect to searchd server and update given MVA attributes on given document in given indexes.
   * Sample code that will set group_id=(123, 456, 789) where id=10
   *
   * <pre>
   * String[] attrs = new String[1];
   *
   * attrs[0] = "group_id";
   * int[][] values = new int[1][3];
   *
   * values[0] = new int[3]; values[0][0] = 123; values[0][1] = 456; values[0][2] = 789
   *
   * int res = cl.UpdateAttributesMVA ( "test1", 10, attrs, values );
   * </pre>
   *
   * @param index index name(s) to update; might be distributed
   * @param docid id of document to update
   * @param attrs array with the names of the attributes to update
   * @param values array of updates; each int[] entry must contains all new attribute values
   * @param ignorenonexistent the flag whether to silently ignore non existent columns up update
   *     request
   * @return -1 on failure, amount of actually found and updated documents (might be 0) on success
   * @throws SphinxException on invalid parameters
   */
  public int UpdateAttributesMVA(
      String index, long docid, String[] attrs, int[][] values, boolean ignorenonexistent)
      throws SphinxException {
    /* check args */
    myAssert(index != null && index.length() > 0, "no index name provided");
    myAssert(docid > 0, "invalid document id");
    myAssert(attrs != null && attrs.length > 0, "no attribute names provided");
    myAssert(values != null && values.length > 0, "no update entries provided");
    myAssert(values.length == attrs.length, "update entry has wrong length");
    for (int i = 0; i < values.length; i++) {
      myAssert(values[i] != null, "update entry #" + i + " is null");
    }

    /* build and send request */
    ByteArrayOutputStream reqBuf = new ByteArrayOutputStream();
    DataOutputStream req = new DataOutputStream(reqBuf);
    try {
      writeNetUTF8(req, index);

      req.writeInt(attrs.length);
      req.writeInt(ignorenonexistent ? 1 : 0);
      for (int i = 0; i < attrs.length; i++) {
        writeNetUTF8(req, attrs[i]);
        req.writeInt(1); // MVA attr
      }

      req.writeInt(1);
      req.writeLong(docid); /* send docid as 64bit value */

      for (int i = 0; i < values.length; i++) {
        req.writeInt(values[i].length); /* send MVA's count */
        for (int j = 0; j < values[i].length; j++) /* send MVAs itself*/ req.writeInt(values[i][j]);
      }

      req.flush();

    } catch (Exception e) {
      _error = "internal error: failed to build request: " + e;
      return -1;
    }

    /* get and parse response */
    DataInputStream in = _DoRequest(SEARCHD_COMMAND_UPDATE, VER_COMMAND_UPDATE, reqBuf);
    if (in == null) return -1;

    try {
      return in.readInt();
    } catch (Exception e) {
      _error = "incomplete reply";
      return -1;
    }
  }
Example #6
0
  /** Set values filter. Only match records where attribute value is in given set. */
  public void SetFilter(String attribute, long[] values, boolean exclude) throws SphinxException {
    myAssert(values != null && values.length > 0, "values array must not be null or empty");
    myAssert(
        attribute != null && attribute.length() > 0, "attribute name must not be null or empty");

    try {
      writeNetUTF8(_filters, attribute);
      _filters.writeInt(SPH_FILTER_VALUES);
      _filters.writeInt(values.length);
      for (int i = 0; i < values.length; i++) _filters.writeLong(values[i]);
      _filters.writeInt(exclude ? 1 : 0);

    } catch (Exception e) {
      myAssert(false, "IOException: " + e.getMessage());
    }
    _filterCount++;
  }
Example #7
0
  /**
   * Connect to searchd server, and generate keyword list for a given query. Returns null on
   * failure, an array of Maps with misc per-keyword info on success.
   */
  public Map[] BuildKeywords(String query, String index, boolean hits) throws SphinxException {
    /* build request */
    ByteArrayOutputStream reqBuf = new ByteArrayOutputStream();
    DataOutputStream req = new DataOutputStream(reqBuf);
    try {
      writeNetUTF8(req, query);
      writeNetUTF8(req, index);
      req.writeInt(hits ? 1 : 0);

    } catch (Exception e) {
      _error = "internal error: failed to build request: " + e;
      return null;
    }

    /* run request */
    DataInputStream in = _DoRequest(SEARCHD_COMMAND_KEYWORDS, VER_COMMAND_KEYWORDS, reqBuf);
    if (in == null) return null;

    /* parse reply */
    try {
      int iNumWords = in.readInt();
      Map[] res = new Map[iNumWords];

      for (int i = 0; i < iNumWords; i++) {
        res[i] = new LinkedHashMap();
        res[i].put("tokenized", readNetUTF8(in));
        res[i].put("normalized", readNetUTF8(in));
        if (hits) {
          res[i].put("docs", new Long(readDword(in)));
          res[i].put("hits", new Long(readDword(in)));
        }
      }
      return res;

    } catch (Exception e) {
      _error = "incomplete reply";
      return null;
    }
  }
Example #8
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;
  }
Example #9
0
  /** Run all previously added search queries. */
  public SphinxResult[] RunQueries() throws SphinxException {
    if (_reqs == null || _reqs.size() < 1) {
      _error = "no queries defined, issue AddQuery() first";
      return null;
    }

    /* build the mega-request */
    int nreqs = _reqs.size();
    ByteArrayOutputStream reqBuf = new ByteArrayOutputStream();
    try {
      DataOutputStream req = new DataOutputStream(reqBuf);
      /* its a client */
      req.writeInt(0);
      req.writeInt(nreqs);
      for (int i = 0; i < nreqs; i++) req.write((byte[]) _reqs.get(i));
      req.flush();

    } catch (Exception e) {
      _error = "internal error: failed to build request: " + e;
      return null;
    }

    DataInputStream in = _DoRequest(SEARCHD_COMMAND_SEARCH, VER_COMMAND_SEARCH, reqBuf);
    if (in == null) return null;

    SphinxResult[] results = new SphinxResult[nreqs];
    _reqs = new ArrayList();

    try {
      for (int ires = 0; ires < nreqs; ires++) {
        SphinxResult res = new SphinxResult();
        results[ires] = res;

        int status = in.readInt();
        res.setStatus(status);
        if (status != SEARCHD_OK) {
          String message = readNetUTF8(in);
          if (status == SEARCHD_WARNING) {
            res.warning = message;
          } else {
            res.error = message;
            continue;
          }
        }

        /* read fields */
        int nfields = in.readInt();
        res.fields = new String[nfields];
        int pos = 0;
        for (int i = 0; i < nfields; i++) res.fields[i] = readNetUTF8(in);

        /* read arrts */
        int nattrs = in.readInt();
        res.attrTypes = new int[nattrs];
        res.attrNames = new String[nattrs];
        for (int i = 0; i < nattrs; i++) {
          String AttrName = readNetUTF8(in);
          int AttrType = in.readInt();
          res.attrNames[i] = AttrName;
          res.attrTypes[i] = AttrType;
        }

        /* read match count */
        int count = in.readInt();
        int id64 = in.readInt();
        res.matches = new SphinxMatch[count];
        for (int matchesNo = 0; matchesNo < count; matchesNo++) {
          SphinxMatch docInfo;
          docInfo = new SphinxMatch((id64 == 0) ? readDword(in) : in.readLong(), in.readInt());

          /* read matches */
          for (int attrNumber = 0; attrNumber < res.attrTypes.length; attrNumber++) {
            String attrName = res.attrNames[attrNumber];
            int type = res.attrTypes[attrNumber];

            /* handle bigints */
            if (type == SPH_ATTR_BIGINT) {
              docInfo.attrValues.add(attrNumber, new Long(in.readLong()));
              continue;
            }

            /* handle floats */
            if (type == SPH_ATTR_FLOAT) {
              docInfo.attrValues.add(attrNumber, new Float(in.readFloat()));
              continue;
            }

            /* handle strings */
            if (type == SPH_ATTR_STRING) {
              String s = readNetUTF8(in);
              docInfo.attrValues.add(attrNumber, s);
              continue;
            }

            /* handle everything else as unsigned ints */
            long val = readDword(in);
            if (type == SPH_ATTR_MULTI) {
              long[] vals = new long[(int) val];
              for (int k = 0; k < val; k++) vals[k] = readDword(in);

              docInfo.attrValues.add(attrNumber, vals);

            } else if (type == SPH_ATTR_MULTI64) {
              val = val / 2;
              long[] vals = new long[(int) val];
              for (int k = 0; k < val; k++) vals[k] = in.readLong();

              docInfo.attrValues.add(attrNumber, vals);

            } else {
              docInfo.attrValues.add(attrNumber, new Long(val));
            }
          }
          res.matches[matchesNo] = docInfo;
        }

        res.total = in.readInt();
        res.totalFound = in.readInt();
        res.time = in.readInt() / 1000.0f;

        res.words = new SphinxWordInfo[in.readInt()];
        for (int i = 0; i < res.words.length; i++)
          res.words[i] = new SphinxWordInfo(readNetUTF8(in), readDword(in), readDword(in));
      }
      return results;

    } catch (IOException e) {
      _error = "incomplete reply";
      return null;
    }
  }
Example #10
0
  /** Add new query with current settings to current search request. */
  public int AddQuery(String query, String index, String comment) throws SphinxException {
    ByteArrayOutputStream req = new ByteArrayOutputStream();

    /* build request */
    try {
      DataOutputStream out = new DataOutputStream(req);
      out.writeInt(_offset);
      out.writeInt(_limit);
      out.writeInt(_mode);
      out.writeInt(_ranker);
      if (_ranker == SPH_RANK_EXPR) {
        writeNetUTF8(out, _rankexpr);
      }
      out.writeInt(_sort);
      writeNetUTF8(out, _sortby);
      writeNetUTF8(out, query);
      int weightLen = _weights != null ? _weights.length : 0;

      out.writeInt(weightLen);
      if (_weights != null) {
        for (int i = 0; i < _weights.length; i++) out.writeInt(_weights[i]);
      }

      writeNetUTF8(out, index);
      out.writeInt(0);
      out.writeInt(_minId);
      out.writeInt(_maxId);

      /* filters */
      out.writeInt(_filterCount);
      out.write(_rawFilters.toByteArray());

      /* group-by, max matches, sort-by-group flag */
      out.writeInt(_groupFunc);
      writeNetUTF8(out, _groupBy);
      out.writeInt(_maxMatches);
      writeNetUTF8(out, _groupSort);

      out.writeInt(_cutoff);
      out.writeInt(_retrycount);
      out.writeInt(_retrydelay);

      writeNetUTF8(out, _groupDistinct);

      /* anchor point */
      if (_latitudeAttr == null
          || _latitudeAttr.length() == 0
          || _longitudeAttr == null
          || _longitudeAttr.length() == 0) {
        out.writeInt(0);
      } else {
        out.writeInt(1);
        writeNetUTF8(out, _latitudeAttr);
        writeNetUTF8(out, _longitudeAttr);
        out.writeFloat(_latitude);
        out.writeFloat(_longitude);
      }

      /* per-index weights */
      out.writeInt(_indexWeights.size());
      for (Iterator e = _indexWeights.keySet().iterator(); e.hasNext(); ) {
        String indexName = (String) e.next();
        Integer weight = (Integer) _indexWeights.get(indexName);
        writeNetUTF8(out, indexName);
        out.writeInt(weight.intValue());
      }

      /* max query time */
      out.writeInt(_maxQueryTime);

      /* per-field weights */
      out.writeInt(_fieldWeights.size());
      for (Iterator e = _fieldWeights.keySet().iterator(); e.hasNext(); ) {
        String field = (String) e.next();
        Integer weight = (Integer) _fieldWeights.get(field);
        writeNetUTF8(out, field);
        out.writeInt(weight.intValue());
      }

      /* comment */
      writeNetUTF8(out, comment);

      /* overrides */
      out.writeInt(_overrideTypes.size());
      for (Iterator e = _overrideTypes.keySet().iterator(); e.hasNext(); ) {
        String attr = (String) e.next();
        Integer type = (Integer) _overrideTypes.get(attr);
        Map values = (Map) _overrideValues.get(attr);

        writeNetUTF8(out, attr);
        out.writeInt(type.intValue());
        out.writeInt(values.size());

        for (Iterator e2 = values.keySet().iterator(); e2.hasNext(); ) {
          Long id = (Long) e2.next();
          out.writeLong(id.longValue());
          switch (type.intValue()) {
            case SPH_ATTR_FLOAT:
              out.writeFloat(((Float) values.get(id)).floatValue());
              break;
            case SPH_ATTR_BIGINT:
              out.writeLong(((Long) values.get(id)).longValue());
              break;
            default:
              out.writeInt(((Integer) values.get(id)).intValue());
              break;
          }
        }
      }

      /* select-list */
      writeNetUTF8(out, _select);

      /* done! */
      out.flush();
      int qIndex = _reqs.size();
      _reqs.add(qIndex, req.toByteArray());
      return qIndex;

    } catch (Exception e) {
      myAssert(false, "error in AddQuery(): " + e + ": " + e.getMessage());

    } finally {
      try {
        _filters.close();
        _rawFilters.close();
      } catch (IOException e) {
        myAssert(false, "error in AddQuery(): " + e + ": " + e.getMessage());
      }
    }
    return -1;
  }
Example #11
0
  /**
   * Connect to searchd server and generate excerpts (snippets) from given documents.
   *
   * @param opts maps String keys to String or Integer values (see the documentation for complete
   *     keys list).
   * @return null on failure, array of snippets on success.
   */
  public String[] BuildExcerpts(String[] docs, String index, String words, Map opts)
      throws SphinxException {
    myAssert(docs != null && docs.length > 0, "BuildExcerpts: Have no documents to process");
    myAssert(
        index != null && index.length() > 0, "BuildExcerpts: Have no index to process documents");
    myAssert(words != null && words.length() > 0, "BuildExcerpts: Have no words to highlight");
    if (opts == null) opts = new LinkedHashMap();

    /* fixup options */
    if (!opts.containsKey("before_match")) opts.put("before_match", "<b>");
    if (!opts.containsKey("after_match")) opts.put("after_match", "</b>");
    if (!opts.containsKey("chunk_separator")) opts.put("chunk_separator", "...");
    if (!opts.containsKey("html_strip_mode")) opts.put("html_strip_mode", "index");
    if (!opts.containsKey("limit")) opts.put("limit", new Integer(256));
    if (!opts.containsKey("limit_passages")) opts.put("limit_passages", new Integer(0));
    if (!opts.containsKey("limit_words")) opts.put("limit_words", new Integer(0));
    if (!opts.containsKey("around")) opts.put("around", new Integer(5));
    if (!opts.containsKey("start_passage_id")) opts.put("start_passage_id", new Integer(1));
    if (!opts.containsKey("exact_phrase")) opts.put("exact_phrase", new Integer(0));
    if (!opts.containsKey("single_passage")) opts.put("single_passage", new Integer(0));
    if (!opts.containsKey("use_boundaries")) opts.put("use_boundaries", new Integer(0));
    if (!opts.containsKey("weight_order")) opts.put("weight_order", new Integer(0));
    if (!opts.containsKey("load_files")) opts.put("load_files", new Integer(0));
    if (!opts.containsKey("allow_empty")) opts.put("allow_empty", new Integer(0));
    if (!opts.containsKey("query_mode")) opts.put("query_mode", new Integer(0));
    if (!opts.containsKey("force_all_words")) opts.put("force_all_words", new Integer(0));

    /* build request */
    ByteArrayOutputStream reqBuf = new ByteArrayOutputStream();
    DataOutputStream req = new DataOutputStream(reqBuf);
    try {
      req.writeInt(0);
      int iFlags = 1; /* remove_spaces */
      if (((Integer) opts.get("exact_phrase")).intValue() != 0) iFlags |= 2;
      if (((Integer) opts.get("single_passage")).intValue() != 0) iFlags |= 4;
      if (((Integer) opts.get("use_boundaries")).intValue() != 0) iFlags |= 8;
      if (((Integer) opts.get("weight_order")).intValue() != 0) iFlags |= 16;
      if (((Integer) opts.get("query_mode")).intValue() != 0) iFlags |= 32;
      if (((Integer) opts.get("force_all_words")).intValue() != 0) iFlags |= 64;
      if (((Integer) opts.get("load_files")).intValue() != 0) iFlags |= 128;
      if (((Integer) opts.get("allow_empty")).intValue() != 0) iFlags |= 256;
      req.writeInt(iFlags);
      writeNetUTF8(req, index);
      writeNetUTF8(req, words);

      /* send options */
      writeNetUTF8(req, (String) opts.get("before_match"));
      writeNetUTF8(req, (String) opts.get("after_match"));
      writeNetUTF8(req, (String) opts.get("chunk_separator"));
      req.writeInt(((Integer) opts.get("limit")).intValue());
      req.writeInt(((Integer) opts.get("around")).intValue());

      req.writeInt(((Integer) opts.get("limit_passages")).intValue());
      req.writeInt(((Integer) opts.get("limit_words")).intValue());
      req.writeInt(((Integer) opts.get("start_passage_id")).intValue());
      writeNetUTF8(req, (String) opts.get("html_strip_mode"));

      /* send documents */
      req.writeInt(docs.length);
      for (int i = 0; i < docs.length; i++) writeNetUTF8(req, docs[i]);

      req.flush();

    } catch (Exception e) {
      _error = "internal error: failed to build request: " + e;
      return null;
    }

    DataInputStream in = _DoRequest(SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, reqBuf);
    if (in == null) return null;

    try {
      String[] res = new String[docs.length];
      for (int i = 0; i < docs.length; i++) res[i] = readNetUTF8(in);
      return res;

    } catch (Exception e) {
      _error = "incomplete reply";
      return null;
    }
  }