1 /* 2 * Copyright (C) 2017, Google Inc. 3 * and other copyright owners as documented in the project's IP log. 4 * 5 * This program and the accompanying materials are made available 6 * under the terms of the Eclipse Distribution License v1.0 which 7 * accompanies this distribution, is reproduced below, and is 8 * available at http://www.eclipse.org/org/documents/edl-v10.php 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * - Neither the name of the Eclipse Foundation, Inc. nor the 25 * names of its contributors may be used to endorse or promote 26 * products derived from this software without specific prior 27 * written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 package org.eclipse.jgit.internal.storage.io; 45 46 import java.io.FileInputStream; 47 import java.io.IOException; 48 import java.nio.ByteBuffer; 49 import java.nio.channels.FileChannel; 50 51 /** 52 * Provides content blocks of file. 53 * <p> 54 * {@code BlockSource} implementations must decide if they will be thread-safe, 55 * or not. 56 */ 57 public abstract class BlockSource implements AutoCloseable { 58 /** 59 * Wrap a byte array as a {@code BlockSource}. 60 * 61 * @param content 62 * input file. 63 * @return block source to read from {@code content}. 64 */ 65 public static BlockSource from(byte[] content) { 66 return new BlockSource() { 67 @Override 68 public ByteBuffer read(long pos, int cnt) { 69 ByteBuffer buf = ByteBuffer.allocate(cnt); 70 if (pos < content.length) { 71 int p = (int) pos; 72 int n = Math.min(cnt, content.length - p); 73 buf.put(content, p, n); 74 } 75 return buf; 76 } 77 78 @Override 79 public long size() { 80 return content.length; 81 } 82 83 @Override 84 public void close() { 85 // Do nothing. 86 } 87 }; 88 } 89 90 /** 91 * Read from a {@code FileInputStream}. 92 * <p> 93 * The returned {@code BlockSource} is not thread-safe, as it must seek the 94 * file channel to read a block. 95 * 96 * @param in 97 * the file. The {@code BlockSource} will close {@code in}. 98 * @return wrapper for {@code in}. 99 */ 100 public static BlockSource from(FileInputStream in) { 101 return from(in.getChannel()); 102 } 103 104 /** 105 * Read from a {@code FileChannel}. 106 * <p> 107 * The returned {@code BlockSource} is not thread-safe, as it must seek the 108 * file channel to read a block. 109 * 110 * @param ch 111 * the file. The {@code BlockSource} will close {@code ch}. 112 * @return wrapper for {@code ch}. 113 */ 114 public static BlockSource from(FileChannel ch) { 115 return new BlockSource() { 116 @Override 117 public ByteBuffer read(long pos, int blockSize) throws IOException { 118 ByteBuffer b = ByteBuffer.allocate(blockSize); 119 ch.position(pos); 120 int n; 121 do { 122 n = ch.read(b); 123 } while (n > 0 && b.position() < blockSize); 124 return b; 125 } 126 127 @Override 128 public long size() throws IOException { 129 return ch.size(); 130 } 131 132 @Override 133 public void close() { 134 try { 135 ch.close(); 136 } catch (IOException e) { 137 // Ignore close failures of read-only files. 138 } 139 } 140 }; 141 } 142 143 /** 144 * Read a block from the file. 145 * <p> 146 * To reduce copying, the returned ByteBuffer should have an accessible 147 * array and {@code arrayOffset() == 0}. The caller will discard the 148 * ByteBuffer and directly use the backing array. 149 * 150 * @param position 151 * position of the block in the file, specified in bytes from the 152 * beginning of the file. 153 * @param blockSize 154 * size to read. 155 * @return buffer containing the block content. 156 * @throws java.io.IOException 157 * if block cannot be read. 158 */ 159 public abstract ByteBuffer read(long position, int blockSize) 160 throws IOException; 161 162 /** 163 * Determine the size of the file. 164 * 165 * @return total number of bytes in the file. 166 * @throws java.io.IOException 167 * if size cannot be obtained. 168 */ 169 public abstract long size() throws IOException; 170 171 /** 172 * Advise the {@code BlockSource} a sequential scan is starting. 173 * 174 * @param startPos 175 * starting position. 176 * @param endPos 177 * ending position. 178 */ 179 public void adviseSequentialRead(long startPos, long endPos) { 180 // Do nothing by default. 181 } 182 183 /** {@inheritDoc} */ 184 @Override 185 public abstract void close(); 186 }