Skip to content

Commit

Permalink
SOLR-17588 : javabin must support primitive arrays (#2900)
Browse files Browse the repository at this point in the history
  • Loading branch information
noblepaul committed Jan 8, 2025
1 parent b250374 commit fa52b8b
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 0 deletions.
144 changes: 144 additions & 0 deletions solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public class JavaBinCodec implements PushWriter {
MAP_ENTRY = 19,
UUID = 20, // This is reserved to be used only in LogCodec
// types that combine tag + length (or other info) in a single byte
PRIMITIVE_ARR = 21,
TAG_AND_LEN = (byte) (1 << 5),
STR = (byte) (1 << 5),
SINT = (byte) (2 << 5),
Expand Down Expand Up @@ -348,6 +349,8 @@ protected Object readObject(DataInputInputStream dis) throws IOException {
return readMapEntry(dis);
case MAP_ENTRY_ITER:
return readMapIter(dis);
case PRIMITIVE_ARR:
return readPrimitiveArray(dis);
}

throw new RuntimeException("Unknown type " + tagByte);
Expand Down Expand Up @@ -438,9 +441,150 @@ public boolean writeKnownType(Object val) throws IOException {
writeBoolean(((AtomicBoolean) val).get());
return true;
}
if (val instanceof float[] ff) {
writeFloatArr(ff);
return true;
}
if (val instanceof int[] ii) {
writeIntArr(ii);
return true;
}
if (val instanceof long[] ll) {
writeLongArr(ll);
return true;
}
if (val instanceof double[] dd) {
writeDoubleArr(dd);
return true;
}
if (val instanceof short[] ss) {
writeShortArr(ss);
return true;
}
if (val instanceof boolean[] bb) {
writeBoolArr(bb);
return true;
}
return false;
}

public Object readPrimitiveArray(DataInputInputStream dis) throws IOException {
tagByte = dis.readByte();
int len = readVInt(dis);
switch (tagByte) {
case FLOAT:
{
float[] v = new float[len];
for (int i = 0; i < len; i++) {
v[i] = dis.readFloat();
}
return v;
}
case INT:
{
int[] v = new int[len];
for (int i = 0; i < len; i++) {
v[i] = dis.readInt();
}
return v;
}

case LONG:
{
long[] v = new long[len];
for (int i = 0; i < len; i++) {
v[i] = dis.readLong();
}
return v;
}
case DOUBLE:
{
double[] v = new double[len];
for (int i = 0; i < len; i++) {
v[i] = dis.readDouble();
}
return v;
}
case SHORT:
{
short[] v = new short[len];
for (int i = 0; i < len; i++) {
v[i] = dis.readShort();
}
return v;
}
case BOOL_TRUE:
case BOOL_FALSE:
{
boolean[] v = new boolean[len];
for (int i = 0; i < len; i++) {
byte b = dis.readByte();
v[i] = b == BOOL_FALSE ? false : true;
}
return v;
}
case BYTE:
{
// it should be possible to serialize byte[] in the new format as well
byte[] v = new byte[len];
dis.readFully(v);
return v;
}
default:
{
throw new RuntimeException("Invalid type : " + tagByte);
}
}
}

public void writePrimitiveArrHeader(byte tag, int len) throws IOException {
writeTag(PRIMITIVE_ARR);
writeTag(tag);
writeVInt(len, daos);
}

public void writeFloatArr(float[] vals) throws IOException {
writePrimitiveArrHeader(FLOAT, vals.length);
for (float f : vals) {
daos.writeFloat(f);
}
}

public void writeIntArr(int[] vals) throws IOException {
writePrimitiveArrHeader(INT, vals.length);
for (int i : vals) {
daos.writeInt(i);
}
}

public void writeDoubleArr(double[] vals) throws IOException {
writePrimitiveArrHeader(DOUBLE, vals.length);
for (double d : vals) {
daos.writeDouble(d);
}
}

public void writeLongArr(long[] vals) throws IOException {
writePrimitiveArrHeader(LONG, vals.length);
for (long l : vals) {
daos.writeLong(l);
}
}

public void writeBoolArr(boolean[] vals) throws IOException {
writePrimitiveArrHeader(BOOL_TRUE, vals.length);
for (boolean b : vals) {
writeBoolean(b);
}
}

public void writeShortArr(short[] vals) throws IOException {
writePrimitiveArrHeader(SHORT, vals.length);
for (short l : vals) {
daos.writeShort(l);
}
}

public class BinEntryWriter implements MapWriter.EntryWriter {
@Override
public MapWriter.EntryWriter put(CharSequence k, Object v) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,20 @@ public static SolrDocument generateSolrDocumentWithChildDocs() {
return parentDocument;
}

@Test
public void testPrimitiveArrays() throws Exception {
List<Object> types = new ArrayList<>();

types.add(new float[] {1.0678f, 4.094565f, 0.000456f});
types.add(new double[] {1.0678d, 4.094565d, 0.000456d});
types.add(new int[] {145543, 4546354, 9789857});
types.add(new long[] {145543L, 4546354L, 9789857L});
types.add(new short[] {43, 454, 857});
types.add(new boolean[] {true, true, false});

compareObjects((List<?>) getObject(getBytes(types)), types);
}

private List<Object> generateAllDataTypes() {
List<Object> types = new ArrayList<>();

Expand Down Expand Up @@ -225,6 +239,23 @@ private void compareObjects(List<?> unmarshalledObj, List<?> matchObj) {
} else if (unmarshalledObj.get(i) instanceof SolrInputField
&& matchObj.get(i) instanceof SolrInputField) {
assertTrue(assertSolrInputFieldEquals(unmarshalledObj.get(i), matchObj.get(i)));
} else if (unmarshalledObj.get(i) instanceof float[] a
&& matchObj.get(i) instanceof float[] e) {
assertArrayEquals(e, a, 0.000000f);
} else if (unmarshalledObj.get(i) instanceof double[] a
&& matchObj.get(i) instanceof double[] e) {
assertArrayEquals(e, a, 0.000000d);
} else if (unmarshalledObj.get(i) instanceof long[] a
&& matchObj.get(i) instanceof long[] e) {
assertArrayEquals(e, a);
} else if (unmarshalledObj.get(i) instanceof int[] a && matchObj.get(i) instanceof int[] e) {
assertArrayEquals(e, a);
} else if (unmarshalledObj.get(i) instanceof short[] a
&& matchObj.get(i) instanceof short[] e) {
assertArrayEquals(e, a);
} else if (unmarshalledObj.get(i) instanceof boolean[] a
&& matchObj.get(i) instanceof boolean[] e) {
assertArrayEquals(e, a);
} else {
assertEquals(unmarshalledObj.get(i), matchObj.get(i));
}
Expand Down

0 comments on commit fa52b8b

Please sign in to comment.