View Javadoc
1   /*
2    * Copyright (C) 2010, 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  
11  package org.eclipse.jgit.internal.storage.dfs;
12  
13  import java.io.BufferedInputStream;
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.util.zip.InflaterInputStream;
17  
18  import org.eclipse.jgit.errors.LargeObjectException;
19  import org.eclipse.jgit.errors.MissingObjectException;
20  import org.eclipse.jgit.lib.ObjectId;
21  import org.eclipse.jgit.lib.ObjectLoader;
22  import org.eclipse.jgit.lib.ObjectStream;
23  
24  final class LargePackedWholeObject extends ObjectLoader {
25  	private final int type;
26  
27  	private final long size;
28  
29  	private final long objectOffset;
30  
31  	private final int headerLength;
32  
33  	private final DfsPackFile pack;
34  
35  	private final DfsObjDatabase db;
36  
37  	LargePackedWholeObject(int type, long size, long objectOffset,
38  			int headerLength, DfsPackFile pack, DfsObjDatabase db) {
39  		this.type = type;
40  		this.size = size;
41  		this.objectOffset = objectOffset;
42  		this.headerLength = headerLength;
43  		this.pack = pack;
44  		this.db = db;
45  	}
46  
47  	/** {@inheritDoc} */
48  	@Override
49  	public int getType() {
50  		return type;
51  	}
52  
53  	/** {@inheritDoc} */
54  	@Override
55  	public long getSize() {
56  		return size;
57  	}
58  
59  	/** {@inheritDoc} */
60  	@Override
61  	public boolean isLarge() {
62  		return true;
63  	}
64  
65  	/** {@inheritDoc} */
66  	@Override
67  	public byte[] getCachedBytes() throws LargeObjectException {
68  		throw new LargeObjectException();
69  	}
70  
71  	/** {@inheritDoc} */
72  	@Override
73  	public ObjectStream openStream() throws MissingObjectException, IOException {
74  		PackInputStream packIn;
75  		// ctx is closed by PackInputStream, or explicitly in the finally block
76  		@SuppressWarnings("resource")
77  		DfsReader ctx = db.newReader();
78  		try {
79  			try {
80  				packIn = new PackInputStream(
81  						pack, objectOffset + headerLength, ctx);
82  				ctx = null; // owned by packIn
83  			} catch (IOException packGone) {
84  				// If the pack file cannot be pinned into the cursor, it
85  				// probably was repacked recently. Go find the object
86  				// again and open the stream from that location instead.
87  				ObjectId obj = pack.getReverseIdx(ctx).findObject(objectOffset);
88  				return ctx.open(obj, type).openStream();
89  			}
90  		} finally {
91  			if (ctx != null) {
92  				ctx.close();
93  			}
94  		}
95  
96  		// Align buffer to inflater size, at a larger than default block.
97  		// This reduces the number of context switches from the
98  		// caller down into the pack stream inflation.
99  		int bufsz = 8192;
100 		InputStream in = new BufferedInputStream(
101 				new InflaterInputStream(packIn, packIn.ctx.inflater(), bufsz),
102 				bufsz);
103 		return new ObjectStream.Filter(type, size, in);
104 	}
105 }