Skip to content

Commit 00fd865

Browse files
authored
Merge pull request #1476 from lesserwhirls/docs
Upgrade the documentation theme and use new annotated code blocks feature
2 parents 3232f34 + 9d06ccd commit 00fd865

5 files changed

Lines changed: 326 additions & 300 deletions

File tree

docs/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ gradle.projectsEvaluated { // Several statements below rely upon all subproject
115115

116116
apply from: "$rootDir/gradle/any/properties.gradle" // For Nexus credential properties.
117117

118-
String docTheme = "unidata-jekyll-docs:0.0.5"
118+
String docTheme = "unidata-jekyll-docs:0.0.6"
119119

120120
boolean isGitHub = System.getenv('GITHUB_ACTIONS') as boolean
121121
String imageBaseUrl = "docker.unidata.ucar.edu"
Lines changed: 68 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Disk Caching
3-
last_updated: 2018-10-10
3+
last_updated: 2025-08-15
44
sidebar: netcdfJavaTutorial_sidebar
55
toc: false
66
permalink: disk_caching.html
@@ -12,151 +12,152 @@ permalink: disk_caching.html
1212

1313
#### Writing temporary files using DiskCache
1414

15-
There are a number of places where the CDM library needs to write temporary files to disk. If you end up using the file more than once, its useful to save these files. The CDM uses static methods in <b>_ucar.nc2.util.DiskCache_</b> to manage how the temporary files are managed.
15+
There are a number of places where the CDM library needs to write temporary files to disk. If you end up using the file more than once, its useful to save these files. The CDM uses static methods in `ucar.nc2.util.DiskCache` to manage how the temporary files are managed.
1616

1717
Before the CDM writes the temporary file, it looks to see if it already exists.
1818

19-
1. If a filename ends with <b>_".Z", ".zip", ".gzip", ".gz", or ".bz2", NetcdfFile.open_</b> will write an uncompressed file of the same name, but without the suffix.
19+
1. If a filename ends with `.Z`, `.zip`, `.gzip`, `.gz`, or `.bz2`, `NetcdfFile.open` will write an uncompressed file of the same name, but without the suffix.
2020

21-
2. <b>_Nexrad2_</b>, <b>_Cinrad2_</b> files that are compressed will be uncompressed to a file with an <b>_.uncompress_</b> prefix.
22-
By default, DiskCache prefers to place the temporary file in the same directory as the original file. If it does not have write permission in that directory, by default it will use the directory <b>_${user_home}/.unidata/cache/_</b>. You can change the directory by calling
21+
2. `Nexrad2`, `Cinrad2` files that are compressed will be uncompressed to a file with an `.uncompress` prefix.
22+
By default, DiskCache prefers to place the temporary file in the same directory as the original file. If it does not have write permission in that directory, by default it will use the directory `${user_home}/.unidata/cache/`. You can change the directory by calling
2323

24-
<b>_ucar.nc2.util.DiskCache.setRootDirectory(rootDirectory)._</b>
24+
`ucar.nc2.util.DiskCache.setRootDirectory(rootDirectory).`
2525

2626
You might want to always write temporary files to the cache directory, in order to manage them in a central place. To do so, call
2727

28-
<b>_ucar.nc2.util.DiskCache.setCachePolicy( boolean alwaysInCache)_</b> with parameter <b>_alwaysInCache = true_</b>.
28+
`ucar.nc2.util.DiskCache.setCachePolicy( boolean alwaysInCache)` with parameter `alwaysInCache = true`.
2929

30-
You may want to limit the amount of space the disk cache uses (unless you always have data in writeable directories, so that the disk cache is never used). To scour the cache, call <b>_DiskCache.cleanCache()_</b>. There are several variations of the cleanup:
30+
You may want to limit the amount of space the disk cache uses (unless you always have data in writeable directories, so that the disk cache is never used). To scour the cache, call `DiskCache.cleanCache()`. There are several variations of the cleanup:
3131

32-
* <b>_DiskCache.cleanCache(Date cutoff, StringBuilder sbuff)_</b> will delete files older than the cutoff date.
33-
* <b>_DiskCache.cleanCache(long maxBytes, StringBuilder sbuff)_</b> will retain maxBytes bytes, deleting oldest files first.
34-
* <b>_DiskCache.cleanCache(long maxBytes, Comparator<File> fileComparator, StringBuilder sbuff)_</b> will retain maxBytes bytes, deleting files in the order defined by your Comparator.
32+
* `DiskCache.cleanCache(Date cutoff, StringBuilder sbuff)` will delete files older than the cutoff date.
33+
* `DiskCache.cleanCache(long maxBytes, StringBuilder sbuff)` will retain maxBytes bytes, deleting oldest files first.
34+
* `DiskCache.cleanCache(long maxBytes, Comparator<File> fileComparator, StringBuilder sbuff)` will retain maxBytes bytes, deleting files in the order defined by your Comparator.
3535

36-
For long running application, you might want to do this periodically in a background timer thread, as in the following example.
36+
For a long-running application, you might want to do this periodically in a background timer thread, as in the following example.
3737

38-
~~~
39-
1) Calendar c = Calendar.getInstance(); // contains current startup time
40-
c.add( Calendar.MINUTE, 30); // add 30 minutes to current time // run task every 60 minutes, starting 30 minutes from now
41-
2) java.util.Timer timer = new Timer();
42-
timer.scheduleAtFixedRate( new CacheScourTask(), c.getTime(), (long) 1000 * 60 * 60 );
43-
44-
3) private class CacheScourTask extends java.util.TimerTask {
45-
public void run() {
46-
StringBuffer sbuff = new StringBuffer();
47-
4) DiskCache.cleanCache(100 * 1000 * 1000, sbuff); // 100 Mbytes
48-
sbuff.append("----------------------\n");
49-
5) log.info(sbuff.toString());
50-
}
51-
}
52-
...
53-
// upon exiting
54-
6) timer.cancel();
55-
~~~
5638

57-
1. Get the current time and add 30 minutes to it
58-
2. Start up a timer that executes every 60 minutes, starting in 30 minutes
59-
3. Your class must extend TimerTask, the run method is called by the Timer
60-
4. Scour the cache, allowing 100 Mbytes of space to be retained
61-
5. Optionally log a message with the results of the scour.
62-
6. Make sure you cancel the timer before your application exits, or else the process will not terminate.
39+
~~~java
40+
// Get the current time and add 30 minutes to it
41+
Calendar c = Calendar.getInstance();
42+
c.add(Calendar.MINUTE, 30);
43+
44+
// your class must extend TimerTask, the run method is called by the Timer
45+
private class CacheScourTask extends java.util.TimerTask {
46+
public void run() {
47+
StringBuffer sbuff = new StringBuffer();
48+
//Scour the cache, allowing 100 Mbytes of space to be retained
49+
DiskCache.cleanCache(100 * 1000 * 1000, sbuff);
50+
sbuff.append("----------------------\n");
51+
// Optionally log a message with the results of the scour
52+
log.info(sbuff.toString());
53+
}
54+
}
55+
56+
// Start up a timer that executes every 60 minutes, starting in 30 minutes
57+
java.util.Timer timer = new Timer();
58+
timer.scheduleAtFixedRate(new CacheScourTask(), c.getTime(), (long) 1000 * 60 * 60);
59+
60+
// make sure you cancel the timer before your application exits, or else
61+
// the process will not terminate
62+
timer.cancel();
63+
~~~
6364

6465
#### Writing temporary files using DiskCache2
6566

66-
In a number of places, the <b>_ucar.nc2.util.DiskCache2_</b> class is used to control caching. This does not use static methods, so can be configured for each individual use.
67+
In a number of places, the `ucar.nc2.util.DiskCache2` class is used to control caching. This does not use static methods, so can be configured for each individual use.
6768

68-
The default constructor mimics DiskCache, using <b>_${user_home}/.unidata/cache/</b>_ as the root directory:
69+
The default constructor mimics DiskCache, using `${user_home}/.unidata/cache/` as the root directory:
6970

70-
<b>_DiskCache2 dc2 = new DiskCache2();_</b>
71+
`DiskCache2 dc2 = new DiskCache2();`
7172

7273
You can change the root directory by calling
7374

74-
<b>_dc2.setRootDirectory(rootDirectory)._</b>
75+
`dc2.setRootDirectory(rootDirectory).`
7576

7677
You can tell the class to scour itself in a background timer by using the constructor:
7778

78-
<b>_DiskCache2 dc2 = new DiskCache2(rootDirectory, false, 24 * 60, 60);_</b>
79+
`DiskCache2 dc2 = new DiskCache2(rootDirectory, false, 24 * 60, 60);`
7980

80-
~~~
81+
~~~java
8182
/**
8283
* Create a cache on disk.
8384
* @param root the root directory of the cache. Must be writeable.
8485
* @param relativeToHome if the root directory is relative to the cache home directory.
8586
* @param persistMinutes a file is deleted if its last modified time is greater than persistMinutes
8687
* @param scourEveryMinutes how often to run the scour process. If <= 0, dont scour.
8788
*/
88-
public DiskCache2(String root, boolean relativeToHome, int persistMinutes, int scourEveryMinutes);
89+
public DiskCache2(String root, boolean relativeToHome, int persistMinutes, int scourEveryMinutes);
8990
~~~
9091
9192
You can change the cache policy from the default CachePathPolicy.OneDirectory by (eg):
9293

93-
~~~
94+
~~~java
9495
dc2.setCachePathPolicy(CachePathPolicy.NestedTruncate, null).
9596

96-
/**
97-
* Set the cache path policy
98-
* @param cachePathPolicy one of:
99-
* OneDirectory (default) : replace "/" with "-", so all files are in one directory.
100-
* NestedDirectory: cache files are in nested directories under the root.
101-
* NestedTruncate: eliminate leading directories
102-
*
103-
* @param cachePathPolicyParam for NestedTruncate, eliminate this string
104-
*/
105-
public void setCachePathPolicy(CachePathPolicy cachePathPolicy, String cachePathPolicyParam);
97+
/**
98+
* Set the cache path policy
99+
* @param cachePathPolicy one of:
100+
* OneDirectory (default) : replace "/" with "-", so all files are in one directory.
101+
* NestedDirectory: cache files are in nested directories under the root.
102+
* NestedTruncate: eliminate leading directories
103+
*
104+
* @param cachePathPolicyParam for NestedTruncate, eliminate this string
105+
*/
106+
public void setCachePathPolicy(CachePathPolicy cachePathPolicy, String cachePathPolicyParam);
106107
~~~
107108

108109
You can ensure that the cache is always used with:
109110

110-
<b>_dc2.setCacheAlwaysUsed(true);_</b>
111+
`dc2.setCacheAlwaysUsed(true);`
111112

112113
Otherwise, the cache will try to write the temporary file in the same directory as the data file, and only use the cache if that directory is not writeable.
113114

114115
### GRIB Indexing and Caching
115116

116-
In 4.3 and above, for each GRIB file the CDM writes a _grib index file_ using the filename plus suffix <b>_.gbx9_</b>. So a file named <b>_filename.grib1_</b> will have an index file <b>_filename.grib1.gbx9_</b> created for it the first time that its read. Usually a _cdm index file_ is also created, using the filename plus suffix <b>_.ncx_</b>. So a file named filename.grib1 will have an index file filename.grib1.ncx created for it the first time. When a GRIB file is only part of a collection of GRIB files, then the ncx file may be created only for the collection.
117+
In 4.3 and above, for each GRIB file the CDM writes a _grib index file_ using the filename plus suffix `.gbx9`. So a file named `filename.grib1` will have an index file `filename.grib1.gbx9` created for it the first time that its read. Usually a _cdm index file_ is also created, using the filename plus suffix `.ncx`. So a file named filename.grib1 will have an index file filename.grib1.ncx created for it the first time. When a GRIB file is only part of a collection of GRIB files, then the ncx file may be created only for the collection.
117118

118119
The location of these index files is controlled by a caching strategy. The default strategy is to try to place the index files in the same directory as the data file. If that directory is not writeable, then the default strategy is to write the index files in the default caching directory. In a client application using the CDM, that default will be
119120

120-
<b>_${user_home}/.unidata/cache/._</b>
121+
`${user_home}/.unidata/cache/.`
121122

122123
On the TDS it will be
123-
<b>_${tomcat_home}/content/thredds/cache/cdm_</b>
124+
`${tomcat_home}/content/thredds/cache/cdm`
124125

125126
Clients of the CDM can change the GRIB caching behavior by configuring a DiskCache2 and calling:
126127

127-
<b>_ucar.nc2.grib.GribCollection.setDiskCache2(DiskCache2 dc);_</b>
128+
`ucar.nc2.grib.GribCollection.setDiskCache2(DiskCache2 dc);`
128129

129130
### Object Caching
130131

131132
#### NetcdfFileCache
132133
NetcdfFile objects are cached in memory for performance. When acquired, the object is locked so another thread cannot use. When closed, the lock is removed. When the cache is full, older objects are removed from the cache, and all resources released.
133134

134-
Note that typically a <b>_java.io.RandomAccessFile_</b> object, holding an OS file handle, is open while its in the cache. You must make sure that your cache size is not so large such that you run out of file handles due to NetcdfFile object caching. Most aggregations do not hold more than one file handle open, no matter how many files are in the aggregation. The exception to that is a Union aggregation, which holds each of the files in the union open for the duration of the NetcdfFile object.
135+
Note that typically a `java.io.RandomAccessFile` object, holding an OS file handle, is open while its in the cache. You must make sure that your cache size is not so large such that you run out of file handles due to NetcdfFile object caching. Most aggregations do not hold more than one file handle open, no matter how many files are in the aggregation. The exception to that is a Union aggregation, which holds each of the files in the union open for the duration of the NetcdfFile object.
135136

136137
Holding a file handle open also creates a read lock on some operating systems, which will prevent the file from being opened in write mode.
137138

138139
To enable caching, you must first call
139140

140-
~~~
141-
NetcdfDataset.initNetcdfFileCache(int minElementsInMemory, int maxElementsInMemory, int period);
141+
~~~java
142+
NetcdfDataset.initNetcdfFileCache(int minElementsInMemory, int maxElementsInMemory, int period);
142143
~~~
143144

144-
where _minElementsInMemory_ are the number of objects to keep in the cache when cleaning up, maxElementsInMemory triggers a cleanup if the cache size goes over it, and period specifies the time in seconds to do periodic cleanups.
145+
where `minElementsInMemory` is the number of objects to keep in the cache when cleaning up, `maxElementsInMemory` triggers a cleanup if the cache size goes over it, and `period` specifies the time in seconds to do periodic cleanups.
145146

146147
After enabling, you can disable with:
147148

148-
~~~
149+
~~~java
149150
NetcdfDataset.disableNetcdfFileCache();
150151
~~~
151152

152153
However, you cant reenable after disabling.
153154

154-
Setting <b>_minElementsInMemory_</b> to zero will remove all files not currently in use every <b>_period_</b> seconds.
155+
Setting `minElementsInMemory` to zero will remove all files not currently in use every `period` seconds.
155156

156157
Normally the cleanup is done is a background thread to not interferre with your application, and the maximum elements is approximate. When resources such as file handles must be carefully managed, you can set a hard limit with this call:
157158

158-
~~~
159-
NetcdfDataset.initNetcdfFileCache(int minElementsInMemory, int maxElementsInMemory, int hardLimit, int period);
159+
~~~java
160+
NetcdfDataset.initNetcdfFileCache(int minElementsInMemory, int maxElementsInMemory, int hardLimit, int period);
160161
~~~
161162

162163
so that as soon as the number of NetcdfFile objects exceeds hardLimit , a cleanup is done immediately in the calling thread.

0 commit comments

Comments
 (0)