class Read implements PacketHandler<LobRead> {
        @Override
        public Packet handle(ServerSession session, LobRead packet) {<FILL_FUNCTION_BODY>}
    }

            long lobId = packet.lobId;
            byte[] hmac = packet.hmac;
            long offset = packet.offset;
            int length = packet.length;
            SmallLRUCache<String, InputStream> lobs = session.getLobCache();
            try {
                boolean useTableLobStorage = false;
                int tableId = TransferOutputStream.verifyLobMac(session, hmac, lobId);
                if (tableId < 0) {
                    tableId = -tableId;
                    useTableLobStorage = true;
                }
                String key = tableId + "_" + lobId;
                CachedInputStream cachedInputStream = (CachedInputStream) lobs.get(key);
                if (cachedInputStream == null) {
                    cachedInputStream = new CachedInputStream(null);
                    lobs.put(key, cachedInputStream);
                }
                if (cachedInputStream.getPos() != offset) {
                    DataHandler dh = useTableLobStorage ? session.getDatabase().getDataHandler(tableId)
                            : session.getDatabase();
                    // only the lob id is used
                    ValueLob lob = ValueLob.create(Value.BLOB, dh, tableId, lobId, hmac, -1);
                    lob.setUseTableLobStorage(useTableLobStorage);
                    InputStream lobIn = dh.getLobStorage().getInputStream(lob, hmac, -1);
                    cachedInputStream = new CachedInputStream(lobIn);
                    lobs.put(key, cachedInputStream);
                    lobIn.skip(offset);
                }
                // limit the buffer size
                length = Math.min(16 * Constants.IO_BUFFER_SIZE, length);
                byte[] buff = new byte[length];
                length = IOUtils.readFully(cachedInputStream, buff);
                if (length != buff.length) {
                    byte[] newBuff = new byte[length];
                    System.arraycopy(buff, 0, newBuff, 0, length);
                    buff = newBuff;
                }
                return new LobReadAck(buff);
            } catch (IOException e) {
                throw DbException.convert(e);
            }
        
<methods>public non-sealed void <init>() ,public static PacketHandler#RAW getHandler(com.lealone.server.protocol.PacketType) ,public static PacketHandler#RAW getHandler(int) ,public static void register(com.lealone.server.protocol.PacketType, PacketHandler<? extends com.lealone.server.protocol.Packet>) <variables>private static PacketHandler#RAW[] handlers