public void flattenToBuffer(ByteBuffer buf) throws IOException { buf.putShort((short) m_params.length); for (int i = 0; i < m_params.length; i++) { Object obj = m_params[i]; if ((obj == null) || (obj == JSONObject.NULL)) { VoltType type = VoltType.NULL; buf.put(type.getValue()); continue; } Class<?> cls = obj.getClass(); if (cls.isArray()) { // Since arrays of bytes could be varbinary or strings, // and they are the only kind of array needed by the EE, // special case them as the VARBINARY type. if (obj instanceof byte[]) { final byte[] b = (byte[]) obj; // commented out this bit... presumably the EE will do this check upon recipt /*if (b.length > VoltType.MAX_VALUE_LENGTH) { throw new IOException("Value of byte[] larger than allowed max string or varbinary " + VoltType.MAX_VALUE_LENGTH_STR); }*/ buf.put(VoltType.VARBINARY.getValue()); buf.putInt(b.length); buf.put(b); continue; } // Same as before, but deal with the fact it is coming in as a unmanaged bytebuffer if (obj instanceof BBContainer) { final BBContainer cont = (BBContainer) obj; final ByteBuffer paramBuf = cont.b(); buf.put(VoltType.VARBINARY.getValue()); buf.putInt(paramBuf.remaining()); buf.put(paramBuf); continue; } buf.put(ARRAY); VoltType type; try { type = VoltType.typeFromClass(cls.getComponentType()); } catch (VoltTypeException e) { obj = getAKosherArray((Object[]) obj); cls = obj.getClass(); type = VoltType.typeFromClass(cls.getComponentType()); } buf.put(type.getValue()); switch (type) { case SMALLINT: SerializationHelper.writeArray((short[]) obj, buf); break; case INTEGER: SerializationHelper.writeArray((int[]) obj, buf); break; case BIGINT: SerializationHelper.writeArray((long[]) obj, buf); break; case FLOAT: SerializationHelper.writeArray((double[]) obj, buf); break; case STRING: if (m_encodedStringArrays[i] == null) { // should not happen throw new IOException("String array not encoded"); } // This check used to be done by FastSerializer.writeArray(), but things changed? if (m_encodedStringArrays[i].length > Short.MAX_VALUE) { throw new IOException( "Array exceeds maximum length of " + Short.MAX_VALUE + " bytes"); } buf.putShort((short) m_encodedStringArrays[i].length); for (int zz = 0; zz < m_encodedStringArrays[i].length; zz++) { SerializationHelper.writeVarbinary(m_encodedStringArrays[i][zz], buf); } break; case TIMESTAMP: SerializationHelper.writeArray((TimestampType[]) obj, buf); break; case DECIMAL: // converted long128 in serializer api SerializationHelper.writeArray((BigDecimal[]) obj, buf); break; case VOLTTABLE: SerializationHelper.writeArray((VoltTable[]) obj, buf); break; case VARBINARY: SerializationHelper.writeArray((byte[][]) obj, buf); break; case GEOGRAPHY_POINT: SerializationHelper.writeArray((GeographyPointValue[]) obj, buf); break; case GEOGRAPHY: SerializationHelper.writeArray((GeographyValue[]) obj, buf); break; default: throw new RuntimeException("FIXME: Unsupported type " + type); } continue; } // Handle NULL mappings not encoded by type.min_value convention if (obj == VoltType.NULL_TIMESTAMP) { buf.put(VoltType.TIMESTAMP.getValue()); buf.putLong(VoltType.NULL_BIGINT); // corresponds to EE value.h isNull() continue; } else if (obj == VoltType.NULL_STRING_OR_VARBINARY) { buf.put(VoltType.STRING.getValue()); buf.putInt(VoltType.NULL_STRING_LENGTH); continue; } else if (obj == VoltType.NULL_DECIMAL) { buf.put(VoltType.DECIMAL.getValue()); VoltDecimalHelper.serializeNull(buf); continue; } else if (obj == VoltType.NULL_POINT) { buf.put(VoltType.GEOGRAPHY_POINT.getValue()); GeographyPointValue.serializeNull(buf); continue; } else if (obj == VoltType.NULL_GEOGRAPHY) { buf.put(VoltType.GEOGRAPHY.getValue()); buf.putInt(VoltType.NULL_STRING_LENGTH); continue; } else if (obj instanceof BBContainer) { final BBContainer cont = (BBContainer) obj; final ByteBuffer paramBuf = cont.b(); buf.put(VoltType.VARBINARY.getValue()); buf.putInt(paramBuf.remaining()); buf.put(paramBuf); continue; } VoltType type = VoltType.typeFromClass(cls); buf.put(type.getValue()); switch (type) { case TINYINT: buf.put((Byte) obj); break; case SMALLINT: buf.putShort((Short) obj); break; case INTEGER: buf.putInt((Integer) obj); break; case BIGINT: buf.putLong((Long) obj); break; case FLOAT: if (cls == Float.class) buf.putDouble(((Float) obj).doubleValue()); else if (cls == Double.class) buf.putDouble(((Double) obj).doubleValue()); else throw new RuntimeException("Can't cast parameter type to Double"); break; case STRING: if (m_encodedStrings[i] == null) { // should not happen throw new IOException("String not encoded: " + (String) obj); } SerializationHelper.writeVarbinary(m_encodedStrings[i], buf); break; case TIMESTAMP: long micros = timestampToMicroseconds(obj); buf.putLong(micros); break; case DECIMAL: VoltDecimalHelper.serializeBigDecimal((BigDecimal) obj, buf); break; case VOLTTABLE: ((VoltTable) obj).flattenToBuffer(buf); break; case GEOGRAPHY_POINT: ((GeographyPointValue) obj).flattenToBuffer(buf); break; case GEOGRAPHY: GeographyValue gv = (GeographyValue) obj; buf.putInt(gv.getLengthInBytes()); gv.flattenToBuffer(buf); break; default: throw new RuntimeException("FIXME: Unsupported type " + type); } } }
private static OneParamInfo readOneParameter(ByteBuffer in) throws IOException { Object value; int len; byte[] encodedString = null; byte[][] encodedStringArray = null; byte nextTypeByte = in.get(); if (nextTypeByte == ARRAY) { VoltType nextType = null; byte etype = in.get(); try { nextType = VoltType.get(etype); } catch (AssertionError ae) { throw new RuntimeException("ParameterSet doesn't support type " + etype); } if (nextType == null) { value = null; } else if (nextType == VoltType.STRING) { encodedStringArray = (byte[][]) SerializationHelper.readArray(byte[].class, in); String[] sval = new String[encodedStringArray.length]; for (int i = 0; i < encodedStringArray.length; ++i) { if (encodedStringArray[i] == null) { sval[i] = null; } else { sval[i] = new String(encodedStringArray[i], Constants.UTF8ENCODING); } } value = sval; } else { value = SerializationHelper.readArray(nextType.classFromType(), in); } } else { VoltType nextType; try { nextType = VoltType.get(nextTypeByte); } catch (AssertionError ae) { throw new RuntimeException("ParameterSet doesn't support type " + nextTypeByte); } switch (nextType) { case NULL: value = null; break; case TINYINT: value = in.get(); break; case SMALLINT: value = in.getShort(); break; case INTEGER: value = in.getInt(); break; case BIGINT: value = in.getLong(); break; case FLOAT: value = in.getDouble(); break; case STRING: len = in.getInt(); if (len == VoltType.NULL_STRING_LENGTH) { value = VoltType.NULL_STRING_OR_VARBINARY; } else { encodedString = new byte[len]; in.get(encodedString); value = new String(encodedString, Constants.UTF8ENCODING); } break; case VARBINARY: len = in.getInt(); if (len == VoltType.NULL_STRING_LENGTH) { value = VoltType.NULL_STRING_OR_VARBINARY; } else { encodedString = new byte[len]; in.get(encodedString); value = encodedString; } break; case TIMESTAMP: final long micros = in.getLong(); value = new TimestampType(micros); break; case VOLTTABLE: final int tableSize = in.getInt(); byte[] tableBytes = new byte[tableSize]; in.get(tableBytes); value = PrivateVoltTableFactory.createVoltTableFromBuffer(ByteBuffer.wrap(tableBytes), false); break; case DECIMAL: { BigDecimal decimal_val = SerializationHelper.getBigDecimal(in); if (decimal_val == null) { value = VoltType.NULL_DECIMAL; } else { value = decimal_val; } break; } case GEOGRAPHY_POINT: value = GeographyPointValue.unflattenFromBuffer(in); if (value == null) { value = VoltType.NULL_POINT; } break; case GEOGRAPHY: len = in.getInt(); if (len == VoltType.NULL_STRING_LENGTH) { value = VoltType.NULL_GEOGRAPHY; } else { value = GeographyValue.unflattenFromBuffer(in); } break; case BOOLEAN: value = in.get(); break; default: throw new RuntimeException("ParameterSet doesn't support type " + nextType); } } OneParamInfo retval = new OneParamInfo(); retval.value = value; retval.encodedString = encodedString; retval.encodedStringArray = encodedStringArray; return retval; }