public static String toString(LlapSerDeDataBuffer[][] data) {
    if (data == null) return "null";
    StringBuilder sb = new StringBuilder("[");
    for (int j = 0; j < data.length; ++j) {
      LlapSerDeDataBuffer[] streamData = data[j];
      if (streamData == null) {
        sb.append("null, ");
        continue;
      }
      sb.append("[");
      for (int k = 0; k < streamData.length; ++k) {
        sb.append(streamData[k]);
      }
      sb.append("], ");
    }
    sb.append("]");
    return sb.toString();
  }
RW lock ensures we have a consistent view of the file data, which is important given that
we generate "stripe" boundaries arbitrarily. Reading buffer data itself doesn't require
that this lock is held; however, everything else in stripes list does.
TODO: make more granular? We only care that each one reader sees consistent boundaries.
      So, we could shallow-copy the stripes list, then have individual locks inside each.
llap-server/src/java/org/apache/hadoop/hive/llap/cache/SerDeLowLevelCacheImpl.java