aboutsummaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/fs4/QueryResultPacket.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-search/src/main/java/com/yahoo/fs4/QueryResultPacket.java')
-rw-r--r--container-search/src/main/java/com/yahoo/fs4/QueryResultPacket.java228
1 files changed, 228 insertions, 0 deletions
diff --git a/container-search/src/main/java/com/yahoo/fs4/QueryResultPacket.java b/container-search/src/main/java/com/yahoo/fs4/QueryResultPacket.java
new file mode 100644
index 00000000000..6a27beefb5e
--- /dev/null
+++ b/container-search/src/main/java/com/yahoo/fs4/QueryResultPacket.java
@@ -0,0 +1,228 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.fs4;
+
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A query result packet (code 217). This packet can be decoded only.
+ *
+ * @author bratseth
+ */
+public class QueryResultPacket extends Packet {
+
+ /** The code of this type of package */
+ private static final int code = 217;
+
+ /** Whether mld data is included in this result */
+ private boolean mldFeature = false;
+
+ /** Whether sort data is included in this result */
+ private boolean sortData = false;
+
+ /** Whether coverage information is included in this result */
+ private boolean coverageNodes = false;
+ private long coverageDocs = 0;
+ private long activeDocs = 0;
+ private long soonActiveDocs = 0;
+ private int degradedReason = 0;
+ private short nodesQueried = 0;
+ private short nodesReplied = 0;
+
+ /** Whether the result contains grouping results **/
+ private boolean groupDataFeature = false;
+
+ /** Whether the result contains properties **/
+ private boolean propsFeature = false;
+
+ private long totalDocumentCount;
+
+ private Number maxRank;
+
+ private int docstamp;
+
+ private byte[] groupData = null;
+
+ private List<DocumentInfo> documents=new ArrayList<>(10);
+
+ public FS4Properties[] propsArray;
+
+ private int offset;
+
+ private QueryResultPacket() { }
+
+ public static QueryResultPacket create() {
+ return new QueryResultPacket();
+ }
+
+ public void setDocstamp(int docstamp){ this.docstamp=docstamp; }
+
+ public int getDocstamp() { return docstamp; }
+
+ /** Returns whether this has the mysterious mld feature */
+ public boolean getMldFeature() { return mldFeature; }
+
+ public boolean getCoverageFeature() { return true; }
+
+ public long getCoverageDocs() { return coverageDocs; }
+
+ public long getActiveDocs() { return activeDocs; }
+
+ public long getSoonActiveDocs() { return soonActiveDocs; }
+
+ public int getDegradedReason() { return degradedReason; }
+
+ public boolean getCoverageFull() {
+ return coverageDocs == activeDocs;
+ }
+
+
+ /** @return offset returned by backend */
+ public int getOffset() { return offset; }
+
+ /** Only for testing. */
+ public void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+ @Override
+ public void decodeBody(ByteBuffer buffer) {
+ IntBuffer ints = buffer.asIntBuffer();
+ decodeFeatures(ints);
+ offset = ints.get();
+ int documentCount = ints.get();
+ buffer.position(buffer.position() + ints.position() * 4);
+ totalDocumentCount = buffer.getLong();
+ maxRank = decodeMaxRank(buffer);
+ ints = buffer.asIntBuffer();
+ docstamp = ints.get();
+ buffer.position(buffer.position() + ints.position() * 4);
+ // do not access "ints" below here!
+
+ if (coverageNodes) {
+ nodesQueried = buffer.getShort();
+ nodesReplied = buffer.getShort();
+ }
+
+ byte[][] documentSortData = null;
+ if (sortData && documentCount > 0) {
+ documentSortData = decodeSortData(buffer, documentCount);
+ }
+
+ if (groupDataFeature) {
+ int len = buffer.getInt();
+ groupData = new byte[len];
+ buffer.get(groupData);
+ }
+
+ coverageDocs = buffer.getLong();
+ activeDocs = buffer.getLong();
+ soonActiveDocs = buffer.getLong();
+ degradedReason = buffer.getInt();
+
+ decodeDocuments(buffer, documentCount, documentSortData);
+ if (propsFeature) {
+ int numMaps = buffer.getInt();
+ propsArray = new FS4Properties[numMaps];
+ for (int i = 0; i < numMaps; i++) {
+ propsArray[i] = new FS4Properties();
+ propsArray[i].decode(buffer);
+ }
+ }
+ }
+
+ private byte[][] decodeSortData(ByteBuffer buffer, int documentCount) {
+ int[] indexes = new int[documentCount];
+ indexes[0] = 0;
+ for (int i = 1; i < documentCount; i++) {
+ indexes[i] = buffer.getInt();
+ }
+
+ int sortDataLengthInBytes = buffer.getInt();
+ byte[][] ret = new byte[indexes.length][];
+
+ for (int i = 0; i < indexes.length; i++) {
+ int end = i + 1 >= indexes.length ? sortDataLengthInBytes : indexes[i + 1];
+ int len = end - indexes[i];
+ ret[i] = new byte[len];
+ buffer.get(ret[i], 0, len);
+ }
+ return ret;
+ }
+
+ private Number decodeMaxRank(ByteBuffer buffer) {
+ return Double.valueOf(buffer.getDouble());
+ }
+
+ /**
+ * feature bits
+ */
+ private static final int QRF_MLD = 0x00000001;
+ private static final int QRF_COVERAGE_NODES = 0x00000002;
+ private static final int QRF_SORTDATA = 0x00000010;
+ private static final int QRF_UNUSED_1 = 0x00000020;
+ private static final int QRF_UNUSED_2 = 0x00000040;
+ private static final int QRF_GROUPDATA = 0x00000200;
+ private static final int QRF_PROPERTIES = 0x00000400;
+
+ /** Decodes the feature int of this package data into boolean feature fields */
+ private void decodeFeatures(IntBuffer buffer) {
+ int features = buffer.get();
+ mldFeature = (QRF_MLD & features) != 0;
+ sortData = (QRF_SORTDATA & features) != 0;
+ coverageNodes = (QRF_COVERAGE_NODES & features) != 0;
+ groupDataFeature = (QRF_GROUPDATA & features) != 0;
+ propsFeature = (QRF_PROPERTIES & features) != 0;
+ }
+
+ private void decodeDocuments(ByteBuffer buffer, int documentCount, byte[][] documentSortData) {
+ for (int i = 0; i < documentCount; i++) {
+ byte[] sort = documentSortData == null ? null : documentSortData[i];
+ documents.add(new DocumentInfo(buffer, this, sort));
+ }
+ }
+
+ public int getCode() { return code; }
+
+ protected void codeDecodedHook(int code) {
+ if ( code != QueryResultPacket.code)
+ throw new RuntimeException("Programming error, packet " + getCode() + "Not expected.");
+ }
+
+ public int getDocumentCount() { return documents.size(); }
+
+ public String toString() {
+ return "Query result x packet [" + getDocumentCount() + " documents]";
+ }
+
+ /** Returns the opaque grouping results **/
+ public byte[] getGroupData() { return groupData; }
+
+
+ /** Returns the total number of documents avalable for this query */
+ public long getTotalDocumentCount() { return totalDocumentCount; }
+
+ /** Only for testing. */
+ public void setTotalDocumentCount(long totalDocumentCount) {
+ this.totalDocumentCount = totalDocumentCount;
+ }
+
+ /** Returns a read-only list containing the DocumentInfo objects of this result */
+ public List<DocumentInfo> getDocuments() {
+ return Collections.unmodifiableList(documents);
+ }
+
+ public void addDocument(DocumentInfo document) {
+ documents.add(document);
+ }
+
+ // TODO: Handle new maxRank intelligently
+ public int getMaxRank() { return maxRank.intValue(); }
+
+ public short getNodesQueried() { return nodesQueried; }
+ public short getNodesReplied() { return nodesReplied; }
+
+}