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.pack;
12  
13  import java.lang.ref.ReferenceQueue;
14  import java.lang.ref.SoftReference;
15  
16  import org.eclipse.jgit.storage.pack.PackConfig;
17  
18  class DeltaCache {
19  	private final long size;
20  
21  	private final int entryLimit;
22  
23  	private final ReferenceQueue<byte[]> queue;
24  
25  	private long used;
26  
27  	DeltaCache(PackConfig pc) {
28  		size = pc.getDeltaCacheSize();
29  		entryLimit = pc.getDeltaCacheLimit();
30  		queue = new ReferenceQueue<>();
31  	}
32  
33  	boolean canCache(int length, ObjectToPack./../../../../../org/eclipse/jgit/internal/storage/pack/ObjectToPack.html#ObjectToPack">ObjectToPack src, ObjectToPack res) {
34  		// If the cache would overflow, don't store.
35  		//
36  		if (0 < size && size < used + length) {
37  			checkForGarbageCollectedObjects();
38  			if (0 < size && size < used + length)
39  				return false;
40  		}
41  
42  		if (length < entryLimit) {
43  			used += length;
44  			return true;
45  		}
46  
47  		// If the combined source files are multiple megabytes but the delta
48  		// is on the order of a kilobyte or two, this was likely costly to
49  		// construct. Cache it anyway, even though its over the limit.
50  		//
51  		if (length >> 10 < (src.getWeight() >> 20) + (res.getWeight() >> 21)) {
52  			used += length;
53  			return true;
54  		}
55  
56  		return false;
57  	}
58  
59  	void credit(int reservedSize) {
60  		used -= reservedSize;
61  	}
62  
63  	Ref cache(byte[] data, int actLen, int reservedSize) {
64  		// The caller may have had to allocate more space than is
65  		// required. If we are about to waste anything, shrink it.
66  		//
67  		data = resize(data, actLen);
68  
69  		// When we reserved space for this item we did it for the
70  		// inflated size of the delta, but we were just given the
71  		// compressed version. Adjust the cache cost to match.
72  		//
73  		if (reservedSize != data.length) {
74  			used -= reservedSize;
75  			used += data.length;
76  		}
77  		return new Ref(data, queue);
78  	}
79  
80  	byte[] resize(byte[] data, int actLen) {
81  		if (data.length != actLen) {
82  			byte[] nbuf = new byte[actLen];
83  			System.arraycopy(data, 0, nbuf, 0, actLen);
84  			data = nbuf;
85  		}
86  		return data;
87  	}
88  
89  	private void checkForGarbageCollectedObjects() {
90  		Ref r;
91  		while ((r = (Ref) queue.poll()) != null)
92  			used -= r.cost;
93  	}
94  
95  	static class Ref extends SoftReference<byte[]> {
96  		final int cost;
97  
98  		Ref(byte[] array, ReferenceQueue<byte[]> queue) {
99  			super(array, queue);
100 			cost = array.length;
101 		}
102 	}
103 }