/** * Populate this instance with what we find on the passed in <code>in</code> stream. Can * deserialize protobuf of old Writables format. * * @param in * @throws IOException * @see #write(DataOutputStream) */ void read(final DataInputStream in) throws IOException { // This code is tested over in TestHFileReaderV1 where we read an old hfile w/ this new code. int pblen = ProtobufUtil.lengthOfPBMagic(); byte[] pbuf = new byte[pblen]; if (in.markSupported()) in.mark(pblen); int read = in.read(pbuf); if (read != pblen) throw new IOException("read=" + read + ", wanted=" + pblen); if (ProtobufUtil.isPBMagicPrefix(pbuf)) { parsePB(HFileProtos.FileInfoProto.parseDelimitedFrom(in)); } else { if (in.markSupported()) { in.reset(); parseWritable(in); } else { // We cannot use BufferedInputStream, it consumes more than we read from the underlying IS ByteArrayInputStream bais = new ByteArrayInputStream(pbuf); SequenceInputStream sis = new SequenceInputStream(bais, in); // Concatenate input streams // TODO: Am I leaking anything here wrapping the passed in stream? We are not calling // close on the wrapped // streams but they should be let go after we leave this context? I see that we keep a // reference to the // passed in inputstream but since we no longer have a reference to this after we leave, // we should be ok. parseWritable(new DataInputStream(sis)); } } }
/** * Write out this instance on the passed in <code>out</code> stream. We write it as a protobuf. * * @param out * @throws IOException * @see #read(DataInputStream) */ void write(final DataOutputStream out) throws IOException { HFileProtos.FileInfoProto.Builder builder = HFileProtos.FileInfoProto.newBuilder(); for (Map.Entry<byte[], byte[]> e : this.map.entrySet()) { HBaseProtos.BytesBytesPair.Builder bbpBuilder = HBaseProtos.BytesBytesPair.newBuilder(); bbpBuilder.setFirst(ZeroCopyLiteralByteString.wrap(e.getKey())); bbpBuilder.setSecond(ZeroCopyLiteralByteString.wrap(e.getValue())); builder.addMapEntry(bbpBuilder.build()); } out.write(ProtobufUtil.PB_MAGIC); builder.build().writeDelimitedTo(out); }
/** * Fill our map with content of the pb we read off disk * * @param fip protobuf message to read */ void parsePB(final HFileProtos.FileInfoProto fip) { this.map.clear(); for (BytesBytesPair pair : fip.getMapEntryList()) { this.map.put(pair.getFirst().toByteArray(), pair.getSecond().toByteArray()); } }