Skip to content

Commit dc2bea8

Browse files
committed
Refactor inventory management to use managed-file abstractions, part 1
* Transition thredds.inventory and thredds.filesystem abstractions from java.io/java.nio path APIs (with the exception of their OS implementations) * Add MFileDirectoryStream to support managed-file directory iteration (to replace over-dependence on java.nio.file.DirectoryStream<Path> * Begin migrating GRIB collection, partition, and index code to managed-file abstractions (just enough to compile and pass tests)
1 parent 9c5452c commit dc2bea8

35 files changed

+573
-469
lines changed

cdm-test/src/test/java/thredds/inventory/TestDcm.java

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,6 @@
11
/*
2-
* Copyright (c) 1998 - 2011. University Corporation for Atmospheric Research/Unidata
3-
* Portions of this software were developed by the Unidata Program at the
4-
* University Corporation for Atmospheric Research.
5-
*
6-
* Access and use of this software shall impose the following obligations
7-
* and understandings on the user. The user is granted the right, without
8-
* any fee or cost, to use, copy, modify, alter, enhance and distribute
9-
* this software, and any derivative works thereof, and its supporting
10-
* documentation for any purpose whatsoever, provided that this entire
11-
* notice appears in all copies of the software, derivative works and
12-
* supporting documentation. Further, UCAR requests that the user credit
13-
* UCAR/Unidata in any publications that result from the use of this
14-
* software or in any product that includes this software. The names UCAR
15-
* and/or Unidata, however, may not be used in any advertising or publicity
16-
* to endorse or promote any products or commercial entity unless specific
17-
* written permission is obtained from UCAR/Unidata. The user also
18-
* understands that UCAR/Unidata is not obligated to provide the user with
19-
* any support, consulting, training or assistance of any kind with regard
20-
* to the use, operation and performance of this software nor to provide
21-
* the user with any updates, revisions, new versions or "bug fixes."
22-
*
23-
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
24-
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26-
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
27-
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
28-
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29-
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30-
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
3+
* See LICENSE for license information.
314
*/
325

336
package thredds.inventory;
@@ -41,7 +14,7 @@
4114
import org.slf4j.LoggerFactory;
4215
import thredds.featurecollection.FeatureCollectionConfig;
4316
import thredds.featurecollection.FeatureCollectionType;
44-
import thredds.inventory.filter.StreamFilter;
17+
import thredds.inventory.filter.RegExpMatch;
4518
import thredds.inventory.partition.DirectoryCollection;
4619
import ucar.nc2.time.CalendarDate;
4720
import ucar.unidata.util.test.category.NeedsCdmUnitTest;
@@ -146,7 +119,7 @@ public void testOlderThanInDirectoryCollection() throws IOException {
146119
// String topCollectionName, String topDirS, String olderThan, org.slf4j.Logger logger
147120
DirectoryCollection dcm =
148121
new DirectoryCollection("topCollectionName", specp.getRootDir(), true, config.olderThan, logger);
149-
dcm.setStreamFilter(new StreamFilter(Pattern.compile(".*grib2"), true));
122+
dcm.setStreamFilter(new RegExpMatch(Pattern.compile(".*grib2"), true));
150123

151124
List<String> fileList = dcm.getFilenames();
152125
for (String name : fileList)

cdm-test/src/test/java/thredds/inventory/TestMCollection.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/*
2-
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
5+
56
package thredds.inventory;
67

78
import org.junit.Test;
@@ -10,7 +11,7 @@
1011
import org.slf4j.LoggerFactory;
1112
import thredds.featurecollection.FeatureCollectionConfig;
1213
import thredds.featurecollection.FeatureCollectionType;
13-
import thredds.inventory.filter.StreamFilter;
14+
import thredds.inventory.filter.RegExpMatch;
1415
import thredds.inventory.partition.DirectoryCollection;
1516
import thredds.inventory.partition.TimePartition;
1617
import ucar.unidata.util.test.category.NeedsCdmUnitTest;
@@ -38,10 +39,10 @@ public void testStreamFilterInDirPartition() throws IOException {
3839
Path rootPath = Paths.get(specp.getRootDir());
3940

4041
try (DirectoryCollection dcm =
41-
new DirectoryCollection(config.collectionName, rootPath, true, config.olderThan, logger)) {
42+
new DirectoryCollection(config.collectionName, rootPath.toString(), true, config.olderThan, logger)) {
4243
dcm.putAuxInfo(FeatureCollectionConfig.AUX_CONFIG, config);
4344
if (specp.getFilter() != null)
44-
dcm.setStreamFilter(new StreamFilter(specp.getFilter(), specp.getFilterOnName()));
45+
dcm.setStreamFilter(new RegExpMatch(specp.getFilter(), specp.getFilterOnName()));
4546

4647
int count = 0;
4748
for (MFile mfile : dcm.getFilesSorted()) {

cdm/core/src/main/java/thredds/filesystem/ControllerOS.java

Lines changed: 29 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,19 @@
11
/*
2-
* Copyright (c) 1998 - 2011. University Corporation for Atmospheric Research/Unidata
3-
* Portions of this software were developed by the Unidata Program at the
4-
* University Corporation for Atmospheric Research.
5-
*
6-
* Access and use of this software shall impose the following obligations
7-
* and understandings on the user. The user is granted the right, without
8-
* any fee or cost, to use, copy, modify, alter, enhance and distribute
9-
* this software, and any derivative works thereof, and its supporting
10-
* documentation for any purpose whatsoever, provided that this entire
11-
* notice appears in all copies of the software, derivative works and
12-
* supporting documentation. Further, UCAR requests that the user credit
13-
* UCAR/Unidata in any publications that result from the use of this
14-
* software or in any product that includes this software. The names UCAR
15-
* and/or Unidata, however, may not be used in any advertising or publicity
16-
* to endorse or promote any products or commercial entity unless specific
17-
* written permission is obtained from UCAR/Unidata. The user also
18-
* understands that UCAR/Unidata is not obligated to provide the user with
19-
* any support, consulting, training or assistance of any kind with regard
20-
* to the use, operation and performance of this software nor to provide
21-
* the user with any updates, revisions, new versions or "bug fixes."
22-
*
23-
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
24-
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26-
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
27-
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
28-
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29-
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30-
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
3+
* See LICENSE for license information.
314
*/
325

336
package thredds.filesystem;
347

358
import thredds.inventory.CollectionConfig;
369
import thredds.inventory.MController;
3710
import thredds.inventory.MFile;
11+
import thredds.inventory.MFileDirectoryStream;
3812

3913
import javax.annotation.Nullable;
4014
import javax.annotation.concurrent.ThreadSafe;
4115
import java.io.File;
16+
import java.nio.file.DirectoryStream;
4217
import java.util.*;
4318

4419
/**
@@ -57,7 +32,7 @@ public class ControllerOS implements MController {
5732

5833
@Nullable
5934
@Override
60-
public Iterator<MFile> getInventoryAll(CollectionConfig mc, boolean recheck) {
35+
public DirectoryStream<MFile> getInventoryAll(CollectionConfig mc, boolean recheck) {
6136
String path = mc.getDirectoryName();
6237
if (path.startsWith("file:")) {
6338
path = path.substring(5);
@@ -68,12 +43,12 @@ public Iterator<MFile> getInventoryAll(CollectionConfig mc, boolean recheck) {
6843
return null;
6944
if (!cd.isDirectory())
7045
return null;
71-
return new FilteredIterator(mc, new MFileIteratorAll(cd), false);
46+
return new MFileDirectoryStream(new FilteredIterator(mc, new MFileIteratorAll(cd), false));
7247
}
7348

7449
@Nullable
7550
@Override
76-
public Iterator<MFile> getInventoryTop(CollectionConfig mc, boolean recheck) {
51+
public DirectoryStream<MFile> getInventoryTop(CollectionConfig mc, boolean recheck) {
7752
String path = mc.getDirectoryName();
7853
if (path.startsWith("file:")) {
7954
path = path.substring(5);
@@ -84,11 +59,12 @@ public Iterator<MFile> getInventoryTop(CollectionConfig mc, boolean recheck) {
8459
return null;
8560
if (!cd.isDirectory())
8661
return null;
87-
return new FilteredIterator(mc, new MFileIterator(cd), false); // removes subdirs
62+
return new MFileDirectoryStream(new FilteredIterator(mc, new MFileIterator(cd), false)); // removes subdirs
8863
}
8964

9065
@Nullable
91-
public Iterator<MFile> getSubdirs(CollectionConfig mc, boolean recheck) {
66+
@Override
67+
public DirectoryStream<MFile> getSubdirs(CollectionConfig mc, boolean recheck) {
9268
String path = mc.getDirectoryName();
9369
if (path.startsWith("file:")) {
9470
path = path.substring(5);
@@ -99,7 +75,7 @@ public Iterator<MFile> getSubdirs(CollectionConfig mc, boolean recheck) {
9975
return null;
10076
if (!cd.isDirectory())
10177
return null;
102-
return new FilteredIterator(mc, new MFileIterator(cd), true); // return only subdirs
78+
return new MFileDirectoryStream(new FilteredIterator(mc, new MFileIterator(cd), true)); // return only subdirs
10379
}
10480

10581

@@ -123,14 +99,22 @@ private static class FilteredIterator implements Iterator<MFile> {
12399
}
124100

125101
public boolean hasNext() {
126-
next = nextFilteredFile(); /// 7
102+
if (next != null) {
103+
return true;
104+
}
105+
next = nextFilteredFile();
127106
return (next != null);
128107
}
129108

130109
public MFile next() {
131-
if (next == null)
132-
throw new NoSuchElementException();
133-
return next;
110+
if (next == null) {
111+
if (!hasNext()) {
112+
throw new NoSuchElementException();
113+
}
114+
}
115+
MFile result = next;
116+
next = null;
117+
return result;
134118
}
135119

136120
public void remove() {
@@ -140,16 +124,14 @@ public void remove() {
140124
private MFile nextFilteredFile() {
141125
if (orgIter == null)
142126
return null;
143-
if (!orgIter.hasNext())
144-
return null;
145127

146-
MFile pdata = orgIter.next();
147-
while ((pdata.isDirectory() != wantDirs) || !mc.accept(pdata)) { // skip directories, and filter
148-
if (!orgIter.hasNext())
149-
return null; /// 6
150-
pdata = orgIter.next();
128+
while (orgIter.hasNext()) {
129+
MFile pdata = orgIter.next();
130+
if (pdata.isDirectory() == wantDirs && mc.accept(pdata)) {
131+
return pdata;
132+
}
151133
}
152-
return pdata;
134+
return null;
153135
}
154136
}
155137

cdm/core/src/main/java/thredds/filesystem/ControllerOS7.java

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
55

@@ -8,11 +8,13 @@
88
import thredds.inventory.CollectionConfig;
99
import thredds.inventory.MController;
1010
import thredds.inventory.MFile;
11+
import thredds.inventory.MFileDirectoryStream;
1112
import javax.annotation.concurrent.ThreadSafe;
1213
import java.io.IOException;
1314
import java.nio.file.*;
1415
import java.nio.file.attribute.BasicFileAttributes;
1516
import java.util.Iterator;
17+
import java.util.NoSuchElementException;
1618

1719
/**
1820
* Use Java 7 NIO for scanning the file system
@@ -27,12 +29,12 @@ public class ControllerOS7 implements MController {
2729
////////////////////////////////////////
2830

2931
@Override
30-
public Iterator<MFile> getInventoryAll(CollectionConfig mc, boolean recheck) {
32+
public DirectoryStream<MFile> getInventoryAll(CollectionConfig mc, boolean recheck) {
3133
return null;
3234
}
3335

3436
@Override
35-
public Iterator<MFile> getInventoryTop(CollectionConfig mc, boolean recheck) throws IOException {
37+
public DirectoryStream<MFile> getInventoryTop(CollectionConfig mc, boolean recheck) {
3638
String path = mc.getDirectoryName();
3739
if (path.startsWith("file:")) {
3840
path = path.substring(5);
@@ -41,10 +43,17 @@ public Iterator<MFile> getInventoryTop(CollectionConfig mc, boolean recheck) thr
4143
Path cd = Paths.get(path);
4244
if (!Files.exists(cd))
4345
return null;
44-
return new MFileIterator(cd, new CollectionFilter(mc)); // removes subdirs
46+
MFileDirectoryStream mfileDirStream = null;
47+
try {
48+
mfileDirStream = new MFileDirectoryStream(new MFileIterator(cd, new CollectionFilter(mc))); // removes subdirs
49+
} catch (IOException ioe) {
50+
logger.warn(ioe.getMessage(), ioe);
51+
}
52+
return mfileDirStream;
4553
}
4654

47-
public Iterator<MFile> getSubdirs(CollectionConfig mc, boolean recheck) {
55+
@Override
56+
public DirectoryStream<MFile> getSubdirs(CollectionConfig mc, boolean recheck) {
4857
return null;
4958
}
5059

@@ -68,32 +77,38 @@ public boolean accept(Path entry) {
6877
}
6978

7079
// returns everything in the current directory
71-
private static class MFileIterator implements Iterator<MFile> {
72-
Iterator<Path> dirStream;
80+
private static class MFileIterator implements Iterator<MFile>, AutoCloseable {
81+
private final DirectoryStream<Path> dirStream;
82+
private final Iterator<Path> pathIterator;
7383

7484
MFileIterator(Path dir, DirectoryStream.Filter<Path> filter) throws IOException {
7585
if (filter != null)
76-
dirStream = Files.newDirectoryStream(dir, filter).iterator();
86+
dirStream = Files.newDirectoryStream(dir, filter);
7787
else
78-
dirStream = Files.newDirectoryStream(dir).iterator();
88+
dirStream = Files.newDirectoryStream(dir);
89+
pathIterator = dirStream.iterator();
7990
}
8091

8192
public boolean hasNext() {
82-
return dirStream.hasNext();
93+
return pathIterator.hasNext();
8394
}
8495

8596
public MFile next() {
8697
try {
87-
return new MFileOS7(dirStream.next());
98+
return new MFileOS7(pathIterator.next());
8899
} catch (IOException e) {
89-
e.printStackTrace(); // LOOK we should pass this exception up
90-
throw new RuntimeException(e);
100+
throw new NoSuchElementException(e.getMessage());
91101
}
92102
}
93103

94104
public void remove() {
95105
throw new UnsupportedOperationException();
96106
}
107+
108+
@Override
109+
public void close() throws IOException {
110+
dirStream.close();
111+
}
97112
}
98113

99114
//////////////////////////////////////////////////////////////////

cdm/core/src/main/java/thredds/inventory/CollectionAbstract.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2017 University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
33
* See LICENSE.txt for license information.
44
*/
55

@@ -14,8 +14,6 @@
1414
import ucar.unidata.util.StringUtil2;
1515
import java.io.FileNotFoundException;
1616
import java.io.IOException;
17-
import java.nio.file.DirectoryStream;
18-
import java.nio.file.Path;
1917
import java.util.*;
2018

2119
/**
@@ -109,7 +107,7 @@ public static String cleanName(String name) {
109107
protected DateExtractor dateExtractor;
110108
protected CalendarDate startCollection;
111109
protected long lastModified;
112-
protected DirectoryStream.Filter<Path> sfilter;
110+
protected MFileFilter sfilter;
113111

114112
protected CollectionAbstract(String collectionName, org.slf4j.Logger logger) {
115113
this.collectionName = cleanName(collectionName);
@@ -126,7 +124,7 @@ public String getIndexFilename(String suffix) {
126124
return getRoot() + "/" + collectionName + suffix;
127125
}
128126

129-
public void setStreamFilter(DirectoryStream.Filter<Path> filter) {
127+
public void setStreamFilter(MFileFilter filter) {
130128
this.sfilter = filter;
131129
}
132130

@@ -243,14 +241,6 @@ CalendarDate extractRunDateWithError(MFile mfile) {
243241
}
244242

245243

246-
/////////////////////////////////////////////////////////////////////////
247-
248-
public class MyStreamFilter implements DirectoryStream.Filter<Path> {
249-
public boolean accept(Path entry) throws IOException {
250-
return sfilter == null || sfilter.accept(entry);
251-
}
252-
}
253-
254244
protected List<MFile> makeFileListSorted() throws IOException {
255245
List<MFile> list = new ArrayList<>(100);
256246
try (CloseableIterator<MFile> iter = getFileIterator()) {

0 commit comments

Comments
 (0)