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