1 /* 2 * Copyright (C) 2010, 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.dfs; 45 46 import java.io.BufferedInputStream; 47 import java.io.IOException; 48 import java.io.InputStream; 49 import java.util.zip.InflaterInputStream; 50 51 import org.eclipse.jgit.errors.LargeObjectException; 52 import org.eclipse.jgit.errors.MissingObjectException; 53 import org.eclipse.jgit.lib.ObjectId; 54 import org.eclipse.jgit.lib.ObjectLoader; 55 import org.eclipse.jgit.lib.ObjectStream; 56 57 final class LargePackedWholeObject extends ObjectLoader { 58 private final int type; 59 60 private final long size; 61 62 private final long objectOffset; 63 64 private final int headerLength; 65 66 private final DfsPackFile pack; 67 68 private final DfsObjDatabase db; 69 70 LargePackedWholeObject(int type, long size, long objectOffset, 71 int headerLength, DfsPackFile pack, DfsObjDatabase db) { 72 this.type = type; 73 this.size = size; 74 this.objectOffset = objectOffset; 75 this.headerLength = headerLength; 76 this.pack = pack; 77 this.db = db; 78 } 79 80 @Override 81 public int getType() { 82 return type; 83 } 84 85 @Override 86 public long getSize() { 87 return size; 88 } 89 90 @Override 91 public boolean isLarge() { 92 return true; 93 } 94 95 @Override 96 public byte[] getCachedBytes() throws LargeObjectException { 97 throw new LargeObjectException(); 98 } 99 100 @Override 101 public ObjectStream openStream() throws MissingObjectException, IOException { 102 DfsReader ctx = db.newReader(); 103 InputStream in; 104 try { 105 in = new PackInputStream(pack, objectOffset + headerLength, ctx); 106 } catch (IOException packGone) { 107 // If the pack file cannot be pinned into the cursor, it 108 // probably was repacked recently. Go find the object 109 // again and open the stream from that location instead. 110 // 111 try { 112 ObjectId obj = pack.getReverseIdx(ctx).findObject(objectOffset); 113 return ctx.open(obj, type).openStream(); 114 } finally { 115 ctx.close(); 116 } 117 } finally { 118 ctx.close(); 119 } 120 121 // Align buffer to inflater size, at a larger than default block. 122 // This reduces the number of context switches from the 123 // caller down into the pack stream inflation. 124 int bufsz = 8192; 125 in = new BufferedInputStream( 126 new InflaterInputStream(in, ctx.inflater(), bufsz), 127 bufsz); 128 return new ObjectStream.Filter(type, size, in); 129 } 130 }