1 /*
2 * Copyright (C) 2009, 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.storage.file;
45
46 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
47 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_BASE_CACHE_LIMIT;
48 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACKED_GIT_LIMIT;
49 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACKED_GIT_MMAP;
50 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACKED_GIT_OPENFILES;
51 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACKED_GIT_WINDOWSIZE;
52 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_FILE_TRESHOLD;
53 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PACKED_GIT_USE_STRONGREFS;
54
55 import org.eclipse.jgit.internal.storage.file.WindowCache;
56 import org.eclipse.jgit.lib.Config;
57 import org.eclipse.jgit.storage.pack.PackConfig;
58
59 /**
60 * Configuration parameters for JVM-wide buffer cache used by JGit.
61 */
62 public class WindowCacheConfig {
63 /** 1024 (number of bytes in one kibibyte/kilobyte) */
64 public static final int KB = 1024;
65
66 /** 1024 {@link #KB} (number of bytes in one mebibyte/megabyte) */
67 public static final int MB = 1024 * KB;
68
69 private int packedGitOpenFiles;
70
71 private long packedGitLimit;
72
73 private boolean useStrongRefs;
74
75 private int packedGitWindowSize;
76
77 private boolean packedGitMMAP;
78
79 private int deltaBaseCacheLimit;
80
81 private int streamFileThreshold;
82
83 /**
84 * Create a default configuration.
85 */
86 public WindowCacheConfig() {
87 packedGitOpenFiles = 128;
88 packedGitLimit = 10 * MB;
89 useStrongRefs = false;
90 packedGitWindowSize = 8 * KB;
91 packedGitMMAP = false;
92 deltaBaseCacheLimit = 10 * MB;
93 streamFileThreshold = PackConfig.DEFAULT_BIG_FILE_THRESHOLD;
94 }
95
96 /**
97 * Get maximum number of streams to open at a time.
98 *
99 * @return maximum number of streams to open at a time. Open packs count
100 * against the process limits. <b>Default is 128.</b>
101 */
102 public int getPackedGitOpenFiles() {
103 return packedGitOpenFiles;
104 }
105
106 /**
107 * Set maximum number of streams to open at a time.
108 *
109 * @param fdLimit
110 * maximum number of streams to open at a time. Open packs count
111 * against the process limits
112 */
113 public void setPackedGitOpenFiles(int fdLimit) {
114 packedGitOpenFiles = fdLimit;
115 }
116
117 /**
118 * Get maximum number bytes of heap memory to dedicate to caching pack file
119 * data.
120 *
121 * @return maximum number bytes of heap memory to dedicate to caching pack
122 * file data. <b>Default is 10 MB.</b>
123 */
124 public long getPackedGitLimit() {
125 return packedGitLimit;
126 }
127
128 /**
129 * Set maximum number bytes of heap memory to dedicate to caching pack file
130 * data.
131 *
132 * @param newLimit
133 * maximum number bytes of heap memory to dedicate to caching
134 * pack file data.
135 */
136 public void setPackedGitLimit(long newLimit) {
137 packedGitLimit = newLimit;
138 }
139
140 /**
141 * Get whether the window cache should use strong references or
142 * SoftReferences
143 *
144 * @return {@code true} if the window cache should use strong references,
145 * otherwise it will use {@link java.lang.ref.SoftReference}s
146 * @since 5.1.13
147 */
148 public boolean isPackedGitUseStrongRefs() {
149 return useStrongRefs;
150 }
151
152 /**
153 * Set if the cache should use strong refs or soft refs
154 *
155 * @param useStrongRefs
156 * if @{code true} the cache strongly references cache pages
157 * otherwise it uses {@link java.lang.ref.SoftReference}s which
158 * can be evicted by the Java gc if heap is almost full
159 * @since 5.1.13
160 */
161 public void setPackedGitUseStrongRefs(boolean useStrongRefs) {
162 this.useStrongRefs = useStrongRefs;
163 }
164
165 /**
166 * Get size in bytes of a single window mapped or read in from the pack
167 * file.
168 *
169 * @return size in bytes of a single window mapped or read in from the pack
170 * file. <b>Default is 8 KB.</b>
171 */
172 public int getPackedGitWindowSize() {
173 return packedGitWindowSize;
174 }
175
176 /**
177 * Set size in bytes of a single window read in from the pack file.
178 *
179 * @param newSize
180 * size in bytes of a single window read in from the pack file.
181 */
182 public void setPackedGitWindowSize(int newSize) {
183 packedGitWindowSize = newSize;
184 }
185
186 /**
187 * Whether to use Java NIO virtual memory mapping for windows
188 *
189 * @return {@code true} enables use of Java NIO virtual memory mapping for
190 * windows; false reads entire window into a byte[] with standard
191 * read calls. <b>Default false.</b>
192 */
193 public boolean isPackedGitMMAP() {
194 return packedGitMMAP;
195 }
196
197 /**
198 * Set whether to enable use of Java NIO virtual memory mapping for windows
199 *
200 * @param usemmap
201 * {@code true} enables use of Java NIO virtual memory mapping
202 * for windows; false reads entire window into a byte[] with
203 * standard read calls.
204 */
205 public void setPackedGitMMAP(boolean usemmap) {
206 packedGitMMAP = usemmap;
207 }
208
209 /**
210 * Get maximum number of bytes to cache in delta base cache for inflated,
211 * recently accessed objects, without delta chains.
212 *
213 * @return maximum number of bytes to cache in delta base cache for
214 * inflated, recently accessed objects, without delta chains.
215 * <b>Default 10 MB.</b>
216 */
217 public int getDeltaBaseCacheLimit() {
218 return deltaBaseCacheLimit;
219 }
220
221 /**
222 * Set maximum number of bytes to cache in delta base cache for inflated,
223 * recently accessed objects, without delta chains.
224 *
225 * @param newLimit
226 * maximum number of bytes to cache in delta base cache for
227 * inflated, recently accessed objects, without delta chains.
228 */
229 public void setDeltaBaseCacheLimit(int newLimit) {
230 deltaBaseCacheLimit = newLimit;
231 }
232
233 /**
234 * Get the size threshold beyond which objects must be streamed.
235 *
236 * @return the size threshold beyond which objects must be streamed.
237 */
238 public int getStreamFileThreshold() {
239 return streamFileThreshold;
240 }
241
242 /**
243 * Set new byte limit for objects that must be streamed.
244 *
245 * @param newLimit
246 * new byte limit for objects that must be streamed. Objects
247 * smaller than this size can be obtained as a contiguous byte
248 * array, while objects bigger than this size require using an
249 * {@link org.eclipse.jgit.lib.ObjectStream}.
250 */
251 public void setStreamFileThreshold(int newLimit) {
252 streamFileThreshold = newLimit;
253 }
254
255 /**
256 * Update properties by setting fields from the configuration.
257 * <p>
258 * If a property is not defined in the configuration, then it is left
259 * unmodified.
260 *
261 * @param rc
262 * configuration to read properties from.
263 * @return {@code this}.
264 * @since 3.0
265 */
266 public WindowCacheConfig fromConfig(Config rc) {
267 setPackedGitUseStrongRefs(rc.getBoolean(CONFIG_CORE_SECTION,
268 CONFIG_KEY_PACKED_GIT_USE_STRONGREFS,
269 isPackedGitUseStrongRefs()));
270 setPackedGitOpenFiles(rc.getInt(CONFIG_CORE_SECTION, null,
271 CONFIG_KEY_PACKED_GIT_OPENFILES, getPackedGitOpenFiles()));
272 setPackedGitLimit(rc.getLong(CONFIG_CORE_SECTION, null,
273 CONFIG_KEY_PACKED_GIT_LIMIT, getPackedGitLimit()));
274 setPackedGitWindowSize(rc.getInt(CONFIG_CORE_SECTION, null,
275 CONFIG_KEY_PACKED_GIT_WINDOWSIZE, getPackedGitWindowSize()));
276 setPackedGitMMAP(rc.getBoolean(CONFIG_CORE_SECTION, null,
277 CONFIG_KEY_PACKED_GIT_MMAP, isPackedGitMMAP()));
278 setDeltaBaseCacheLimit(rc.getInt(CONFIG_CORE_SECTION, null,
279 CONFIG_KEY_DELTA_BASE_CACHE_LIMIT, getDeltaBaseCacheLimit()));
280
281 long maxMem = Runtime.getRuntime().maxMemory();
282 long sft = rc.getLong(CONFIG_CORE_SECTION, null,
283 CONFIG_KEY_STREAM_FILE_TRESHOLD, getStreamFileThreshold());
284 sft = Math.min(sft, maxMem / 4); // don't use more than 1/4 of the heap
285 sft = Math.min(sft, Integer.MAX_VALUE); // cannot exceed array length
286 setStreamFileThreshold((int) sft);
287 return this;
288 }
289
290 /**
291 * Install this configuration as the live settings.
292 * <p>
293 * The new configuration is applied immediately. If the new limits are
294 * smaller than what is currently cached, older entries will be purged
295 * as soon as possible to allow the cache to meet the new limit.
296 *
297 * @since 3.0
298 */
299 @SuppressWarnings("deprecation")
300 public void install() {
301 WindowCache.reconfigure(this);
302 }
303 }