Skip to content

Commit b32b675

Browse files
mlbiscocMatthew Biscocho
andauthored
SOLR-16903: Migrate from java.io.File to java.nio.file.Path in solr-core (#2924)
Co-authored-by: Matthew Biscocho <[email protected]>
1 parent dac5fe1 commit b32b675

26 files changed

+330
-277
lines changed

solr/CHANGES.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Other Changes
137137

138138
* SOLR-17321: Minimum Java version for Apache Solr is now 21, and for SolrJ, it is 17. (Sanjay Dutt, David Smiley)
139139

140-
* SOLR-16903: Update CLI tools to use java.nio.file.Path instead of java.io.File (Andrey Bozhko)
140+
* SOLR-16903: Update CLI tools and Solr Core to use java.nio.file.Path instead of java.io.File (Andrey Bozhko, Matthew Biscocho)
141141

142142
* SOLR-17568: SolrCloud no longer reroutes/proxies a core request to another node if not found locally. (David Smiley)
143143

solr/core/src/java/org/apache/solr/cloud/ZkSolrResourceLoader.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
package org.apache.solr.cloud;
1818

1919
import java.io.ByteArrayInputStream;
20-
import java.io.File;
2120
import java.io.IOException;
2221
import java.io.InputStream;
2322
import java.lang.invoke.MethodHandles;
23+
import java.nio.file.FileSystems;
2424
import java.nio.file.Path;
2525
import org.apache.solr.common.SolrException.ErrorCode;
2626
import org.apache.solr.common.cloud.ZooKeeperException;
@@ -121,7 +121,9 @@ public InputStream openResource(String resource) throws IOException {
121121

122122
try {
123123
// delegate to the class loader (looking into $INSTANCE_DIR/lib jars)
124-
is = classLoader.getResourceAsStream(resource.replace(File.separatorChar, '/'));
124+
is =
125+
classLoader.getResourceAsStream(
126+
resource.replace(FileSystems.getDefault().getSeparator(), "/"));
125127
} catch (Exception e) {
126128
throw new IOException("Error opening " + resource, e);
127129
}

solr/core/src/java/org/apache/solr/core/CachingDirectoryFactory.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
package org.apache.solr.core;
1818

19-
import java.io.File;
2019
import java.io.IOException;
2120
import java.lang.invoke.MethodHandles;
2221
import java.nio.file.DirectoryStream;
@@ -367,10 +366,7 @@ private void close(CacheValue val) {
367366
}
368367

369368
private static boolean isSubPath(CacheValue cacheValue, CacheValue otherCacheValue) {
370-
int one = cacheValue.path.lastIndexOf(File.separatorChar);
371-
int two = otherCacheValue.path.lastIndexOf(File.separatorChar);
372-
373-
return otherCacheValue.path.startsWith(cacheValue.path + File.separatorChar) && two > one;
369+
return Path.of(otherCacheValue.path).startsWith(Path.of(cacheValue.path));
374370
}
375371

376372
@Override

solr/core/src/java/org/apache/solr/core/CoreDescriptor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
*/
1717
package org.apache.solr.core;
1818

19-
import java.io.File;
2019
import java.io.IOException;
2120
import java.io.Reader;
2221
import java.lang.invoke.MethodHandles;
2322
import java.nio.charset.StandardCharsets;
23+
import java.nio.file.FileSystems;
2424
import java.nio.file.Files;
2525
import java.nio.file.Path;
2626
import java.util.HashMap;
@@ -64,7 +64,7 @@ public class CoreDescriptor {
6464
public static final String SOLR_CORE_PROP_PREFIX = "solr.core.";
6565

6666
public static final String DEFAULT_EXTERNAL_PROPERTIES_FILE =
67-
"conf" + File.separator + "solrcore.properties";
67+
"conf" + FileSystems.getDefault().getSeparator() + "solrcore.properties";
6868

6969
/**
7070
* Whether this core was configured using a configSet that was trusted. This helps in avoiding the
@@ -96,7 +96,7 @@ public Properties getPersistableUserProperties() {
9696
CORE_CONFIG, "solrconfig.xml",
9797
CORE_SCHEMA, "schema.xml",
9898
CORE_CONFIGSET_PROPERTIES, ConfigSetProperties.DEFAULT_FILENAME,
99-
CORE_DATADIR, "data" + File.separator,
99+
CORE_DATADIR, "data" + FileSystems.getDefault().getSeparator(),
100100
CORE_TRANSIENT, "false",
101101
CORE_LOADONSTARTUP, "true");
102102

solr/core/src/java/org/apache/solr/core/DirectoryFactory.java

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@
1717
package org.apache.solr.core;
1818

1919
import java.io.Closeable;
20-
import java.io.File;
21-
import java.io.FileFilter;
2220
import java.io.FileNotFoundException;
2321
import java.io.IOException;
2422
import java.lang.invoke.MethodHandles;
2523
import java.nio.file.Files;
2624
import java.nio.file.NoSuchFileException;
2725
import java.nio.file.Path;
28-
import java.util.Arrays;
29-
import java.util.Collections;
26+
import java.util.Comparator;
3027
import java.util.List;
28+
import java.util.stream.Stream;
3129
import org.apache.commons.io.file.PathUtils;
3230
import org.apache.lucene.store.Directory;
3331
import org.apache.lucene.store.FilterDirectory;
@@ -338,59 +336,68 @@ public String getDataHome(CoreDescriptor cd) throws IOException {
338336
}
339337

340338
public void cleanupOldIndexDirectories(
341-
final String dataDirPath, final String currentIndexDirPath, boolean afterCoreReload) {
339+
final String dataDirPath, final String currentIndexDirPath, boolean afterCoreReload)
340+
throws IOException {
342341

343-
// TODO SOLR-8282 move to PATH
344-
File dataDir = new File(dataDirPath);
345-
if (!dataDir.isDirectory()) {
342+
Path dataDirFile = Path.of(dataDirPath);
343+
if (!Files.isDirectory(dataDirFile)) {
346344
log.debug(
347345
"{} does not point to a valid data directory; skipping clean-up of old index directories.",
348346
dataDirPath);
349347
return;
350348
}
351349

352-
final File currentIndexDir = new File(currentIndexDirPath);
353-
File[] oldIndexDirs =
354-
dataDir.listFiles(
355-
new FileFilter() {
356-
@Override
357-
public boolean accept(File file) {
358-
String fileName = file.getName();
359-
return file.isDirectory()
360-
&& !file.equals(currentIndexDir)
361-
&& (fileName.equals("index") || fileName.matches(INDEX_W_TIMESTAMP_REGEX));
362-
}
363-
});
350+
final Path currentIndexDir = Path.of(currentIndexDirPath);
351+
List<Path> dirsList;
352+
try (Stream<Path> oldIndexDirs = Files.list(dataDirFile)) {
353+
dirsList =
354+
oldIndexDirs
355+
.filter(
356+
(file) -> {
357+
String fileName = file.getFileName().toString();
358+
return Files.isDirectory(file)
359+
&& !file.equals(currentIndexDir)
360+
&& (fileName.equals("index") || fileName.matches(INDEX_W_TIMESTAMP_REGEX));
361+
})
362+
.sorted(Comparator.reverseOrder())
363+
.toList();
364+
}
365+
;
364366

365-
if (oldIndexDirs == null || oldIndexDirs.length == 0)
367+
if (dirsList.isEmpty()) {
366368
return; // nothing to do (no log message needed)
367-
368-
List<File> dirsList = Arrays.asList(oldIndexDirs);
369-
dirsList.sort(Collections.reverseOrder());
369+
}
370370

371371
int i = 0;
372372
if (afterCoreReload) {
373-
log.info("Will not remove most recent old directory after reload {}", oldIndexDirs[0]);
373+
if (log.isInfoEnabled())
374+
log.info("Will not remove most recent old directory after reload {}", dirsList.getFirst());
374375
i = 1;
375376
}
376-
log.info(
377-
"Found {} old index directories to clean-up under {} afterReload={}",
378-
oldIndexDirs.length - i,
379-
dataDirPath,
380-
afterCoreReload);
381-
for (; i < dirsList.size(); i++) {
382-
File dir = dirsList.get(i);
383-
String dirToRmPath = dir.getAbsolutePath();
384-
try {
385-
if (deleteOldIndexDirectory(dirToRmPath)) {
386-
log.info("Deleted old index directory: {}", dirToRmPath);
387-
} else {
388-
log.warn("Delete old index directory {} failed.", dirToRmPath);
389-
}
390-
} catch (IOException ioExc) {
391-
log.error("Failed to delete old directory {} due to: ", dir.getAbsolutePath(), ioExc);
392-
}
393-
}
377+
378+
if (log.isInfoEnabled())
379+
log.info(
380+
"Found {} old index directories to clean-up under {} afterReload={}",
381+
dirsList.size() - i,
382+
dataDirPath,
383+
afterCoreReload);
384+
385+
dirsList.stream()
386+
.skip(i)
387+
.forEach(
388+
(entry) -> {
389+
String dirToRmPath = entry.toAbsolutePath().toString();
390+
try {
391+
if (deleteOldIndexDirectory(dirToRmPath)) {
392+
log.info("Deleted old index directory: {}", dirToRmPath);
393+
} else {
394+
log.warn("Delete old index directory {} failed.", dirToRmPath);
395+
}
396+
} catch (IOException ioExc) {
397+
log.error(
398+
"Failed to delete old directory {} due to: ", entry.toAbsolutePath(), ioExc);
399+
}
400+
});
394401
}
395402

396403
// Extension point to allow subclasses to infuse additional code when deleting old index

solr/core/src/java/org/apache/solr/core/SolrCore.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import com.codahale.metrics.Counter;
2323
import com.codahale.metrics.Timer;
2424
import java.io.Closeable;
25-
import java.io.File;
2625
import java.io.FileNotFoundException;
2726
import java.io.IOException;
2827
import java.io.InputStream;
@@ -33,9 +32,9 @@
3332
import java.lang.invoke.MethodHandles;
3433
import java.lang.reflect.Constructor;
3534
import java.nio.charset.StandardCharsets;
35+
import java.nio.file.Files;
3636
import java.nio.file.NoSuchFileException;
3737
import java.nio.file.Path;
38-
import java.nio.file.Paths;
3938
import java.util.ArrayDeque;
4039
import java.util.ArrayList;
4140
import java.util.Arrays;
@@ -1354,14 +1353,32 @@ public void initializeMetrics(SolrMetricsContext parentContext, String scope) {
13541353
Category.CORE.toString());
13551354
}
13561355

1357-
// TODO SOLR-8282 move to PATH
13581356
// initialize disk total / free metrics
1359-
Path dataDirPath = Paths.get(dataDir);
1360-
File dataDirFile = dataDirPath.toFile();
1357+
Path dataDirPath = Path.of(dataDir);
13611358
parentContext.gauge(
1362-
() -> dataDirFile.getTotalSpace(), true, "totalSpace", Category.CORE.toString(), "fs");
1359+
() -> {
1360+
try {
1361+
return Files.getFileStore(dataDirPath).getTotalSpace();
1362+
} catch (IOException e) {
1363+
return 0L;
1364+
}
1365+
},
1366+
true,
1367+
"totalSpace",
1368+
Category.CORE.toString(),
1369+
"fs");
13631370
parentContext.gauge(
1364-
() -> dataDirFile.getUsableSpace(), true, "usableSpace", Category.CORE.toString(), "fs");
1371+
() -> {
1372+
try {
1373+
return Files.getFileStore(dataDirPath).getUsableSpace();
1374+
} catch (IOException e) {
1375+
return 0L;
1376+
}
1377+
},
1378+
true,
1379+
"usableSpace",
1380+
Category.CORE.toString(),
1381+
"fs");
13651382
parentContext.gauge(
13661383
() -> dataDirPath.toAbsolutePath().toString(),
13671384
true,

solr/core/src/java/org/apache/solr/core/SolrPaths.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
package org.apache.solr.core;
1919

20-
import java.io.File;
2120
import java.lang.invoke.MethodHandles;
21+
import java.nio.file.FileSystems;
2222
import java.nio.file.Path;
2323
import java.nio.file.Paths;
2424
import java.util.Collections;
@@ -44,7 +44,7 @@ private SolrPaths() {} // don't create this
4444
/** Ensures a directory name always ends with a '/'. */
4545
public static String normalizeDir(String path) {
4646
return (path != null && (!(path.endsWith("/") || path.endsWith("\\"))))
47-
? path + File.separator
47+
? path + FileSystems.getDefault().getSeparator()
4848
: path;
4949
}
5050

solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import com.google.common.annotations.VisibleForTesting;
2020
import java.io.Closeable;
21-
import java.io.File;
2221
import java.io.FilterInputStream;
2322
import java.io.IOException;
2423
import java.io.InputStream;
@@ -31,6 +30,7 @@
3130
import java.nio.charset.Charset;
3231
import java.nio.charset.StandardCharsets;
3332
import java.nio.file.DirectoryStream;
33+
import java.nio.file.FileSystems;
3434
import java.nio.file.Files;
3535
import java.nio.file.Path;
3636
import java.nio.file.PathMatcher;
@@ -373,12 +373,16 @@ public InputStream openResource(String resource) throws IOException {
373373

374374
// Delegate to the class loader (looking into $INSTANCE_DIR/lib jars).
375375
// We need a ClassLoader-compatible (forward-slashes) path here!
376-
InputStream is = classLoader.getResourceAsStream(resource.replace(File.separatorChar, '/'));
376+
InputStream is =
377+
classLoader.getResourceAsStream(
378+
resource.replace(FileSystems.getDefault().getSeparator(), "/"));
377379

378380
// This is a hack just for tests (it is not done in ZKResourceLoader)!
379381
// TODO can we nuke this?
380382
if (is == null && System.getProperty("jetty.testMode") != null) {
381-
is = classLoader.getResourceAsStream(("conf/" + resource).replace(File.separatorChar, '/'));
383+
is =
384+
classLoader.getResourceAsStream(
385+
("conf/" + resource.replace(FileSystems.getDefault().getSeparator(), "/")));
382386
}
383387

384388
if (is == null) {
@@ -405,7 +409,8 @@ public String resourceLocation(String resource) {
405409
}
406410

407411
try (InputStream is =
408-
classLoader.getResourceAsStream(resource.replace(File.separatorChar, '/'))) {
412+
classLoader.getResourceAsStream(
413+
resource.replace(FileSystems.getDefault().getSeparator(), "/"))) {
409414
if (is != null) return "classpath:" + resource;
410415
} catch (IOException e) {
411416
// ignore

solr/core/src/java/org/apache/solr/core/backup/BackupManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
*/
1717
package org.apache.solr.core.backup;
1818

19-
import java.io.File;
2019
import java.io.IOException;
2120
import java.io.OutputStream;
2221
import java.io.OutputStreamWriter;
2322
import java.io.Writer;
2423
import java.lang.invoke.MethodHandles;
2524
import java.net.URI;
2625
import java.nio.charset.StandardCharsets;
26+
import java.nio.file.FileSystems;
2727
import java.time.Instant;
2828
import java.util.Collections;
2929
import java.util.List;
@@ -343,7 +343,8 @@ private void downloadConfigToRepo(ConfigSetService configSetService, String conf
343343
// getAllConfigFiles always separates file paths with '/'
344344
for (String filePath : filePaths) {
345345
// Replace '/' to ensure that propre file is resolved for writing.
346-
URI uri = repository.resolve(dir, filePath.replace('/', File.separatorChar));
346+
URI uri =
347+
repository.resolve(dir, filePath.replace("/", FileSystems.getDefault().getSeparator()));
347348
// checking for '/' is correct for a directory since ConfigSetService#getAllConfigFiles
348349
// always separates file paths with '/'
349350
if (!filePath.endsWith("/")) {

0 commit comments

Comments
 (0)