BlockSource.java

  1. /*
  2.  * Copyright (C) 2017, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.internal.storage.io;

  11. import java.io.FileInputStream;
  12. import java.io.IOException;
  13. import java.nio.ByteBuffer;
  14. import java.nio.channels.FileChannel;

  15. /**
  16.  * Provides content blocks of file.
  17.  * <p>
  18.  * {@code BlockSource} implementations must decide if they will be thread-safe,
  19.  * or not.
  20.  */
  21. public abstract class BlockSource implements AutoCloseable {
  22.     /**
  23.      * Wrap a byte array as a {@code BlockSource}.
  24.      *
  25.      * @param content
  26.      *            input file.
  27.      * @return block source to read from {@code content}.
  28.      */
  29.     public static BlockSource from(byte[] content) {
  30.         return new BlockSource() {
  31.             @Override
  32.             public ByteBuffer read(long pos, int cnt) {
  33.                 ByteBuffer buf = ByteBuffer.allocate(cnt);
  34.                 if (pos < content.length) {
  35.                     int p = (int) pos;
  36.                     int n = Math.min(cnt, content.length - p);
  37.                     buf.put(content, p, n);
  38.                 }
  39.                 return buf;
  40.             }

  41.             @Override
  42.             public long size() {
  43.                 return content.length;
  44.             }

  45.             @Override
  46.             public void close() {
  47.                 // Do nothing.
  48.             }
  49.         };
  50.     }

  51.     /**
  52.      * Read from a {@code FileInputStream}.
  53.      * <p>
  54.      * The returned {@code BlockSource} is not thread-safe, as it must seek the
  55.      * file channel to read a block.
  56.      *
  57.      * @param in
  58.      *            the file. The {@code BlockSource} will close {@code in}.
  59.      * @return wrapper for {@code in}.
  60.      */
  61.     public static BlockSource from(FileInputStream in) {
  62.         return from(in.getChannel());
  63.     }

  64.     /**
  65.      * Read from a {@code FileChannel}.
  66.      * <p>
  67.      * The returned {@code BlockSource} is not thread-safe, as it must seek the
  68.      * file channel to read a block.
  69.      *
  70.      * @param ch
  71.      *            the file. The {@code BlockSource} will close {@code ch}.
  72.      * @return wrapper for {@code ch}.
  73.      */
  74.     public static BlockSource from(FileChannel ch) {
  75.         return new BlockSource() {
  76.             @Override
  77.             public ByteBuffer read(long pos, int blockSize) throws IOException {
  78.                 ByteBuffer b = ByteBuffer.allocate(blockSize);
  79.                 ch.position(pos);
  80.                 int n;
  81.                 do {
  82.                     n = ch.read(b);
  83.                 } while (n > 0 && b.position() < blockSize);
  84.                 return b;
  85.             }

  86.             @Override
  87.             public long size() throws IOException {
  88.                 return ch.size();
  89.             }

  90.             @Override
  91.             public void close() {
  92.                 try {
  93.                     ch.close();
  94.                 } catch (IOException e) {
  95.                     // Ignore close failures of read-only files.
  96.                 }
  97.             }
  98.         };
  99.     }

  100.     /**
  101.      * Read a block from the file.
  102.      * <p>
  103.      * To reduce copying, the returned ByteBuffer should have an accessible
  104.      * array and {@code arrayOffset() == 0}. The caller will discard the
  105.      * ByteBuffer and directly use the backing array.
  106.      *
  107.      * @param position
  108.      *            position of the block in the file, specified in bytes from the
  109.      *            beginning of the file.
  110.      * @param blockSize
  111.      *            size to read.
  112.      * @return buffer containing the block content.
  113.      * @throws java.io.IOException
  114.      *             if block cannot be read.
  115.      */
  116.     public abstract ByteBuffer read(long position, int blockSize)
  117.             throws IOException;

  118.     /**
  119.      * Determine the size of the file.
  120.      *
  121.      * @return total number of bytes in the file.
  122.      * @throws java.io.IOException
  123.      *             if size cannot be obtained.
  124.      */
  125.     public abstract long size() throws IOException;

  126.     /**
  127.      * Advise the {@code BlockSource} a sequential scan is starting.
  128.      *
  129.      * @param startPos
  130.      *            starting position.
  131.      * @param endPos
  132.      *            ending position.
  133.      */
  134.     public void adviseSequentialRead(long startPos, long endPos) {
  135.         // Do nothing by default.
  136.     }

  137.     /** {@inheritDoc} */
  138.     @Override
  139.     public abstract void close();
  140. }