-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Add Windows native method to retrieve the number of allocated bytes on disk for file #79698
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
tlrx
merged 24 commits into
elastic:master
from
tlrx:windows-native-method-allocated-file-size
Nov 5, 2021
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
d13a95b
Add Windows native method to retrieve the number of allocated bytes o…
tlrx f4c5d77
test should fail
tlrx 8f95d7b
test should succeed
tlrx 806f501
more docs
tlrx f109191
test
tlrx 0ef20a0
nits + fsync
tlrx 39adb83
debug last failure @TestLogging
tlrx 15abf62
avoid DisableFsyncFS
tlrx d1c4f77
remove @TestLogging
tlrx 2af8a5a
Merge branch 'master' into windows-native-method-allocated-file-size
tlrx 2540f7e
Merge branch 'master' into windows-native-method-allocated-file-size
tlrx ee5ab76
revert changes in boostrap natives
tlrx 2d9275c
add org.elasticsearch.common.filesystem
tlrx 6773071
Merge branch 'master' into windows-native-method-allocated-file-size
tlrx 1cc458f
Merge branch 'master' into windows-native-method-allocated-file-size
tlrx c6ba764
feedback
tlrx e5a0e2c
more
tlrx 9258da1
static method to init static member
tlrx e1aff78
@FunctionalInterface
tlrx c00295f
oneMb
tlrx 853a9de
comment
tlrx 5928b39
INVALID_FILE_SIZE
tlrx 3357e8f
NO_ERROR
tlrx f77c0e0
Merge branch 'master' into windows-native-method-allocated-file-size
tlrx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
server/src/main/java/org/elasticsearch/common/filesystem/FileSystemNatives.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
package org.elasticsearch.common.filesystem; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.lucene.util.Constants; | ||
|
||
import java.nio.file.Path; | ||
import java.util.OptionalLong; | ||
|
||
/** | ||
* This class provides utility methods for calling some native methods related to filesystems. | ||
*/ | ||
public final class FileSystemNatives { | ||
|
||
private static final Logger logger = LogManager.getLogger(FileSystemNatives.class); | ||
|
||
@FunctionalInterface | ||
interface Provider { | ||
OptionalLong allocatedSizeInBytes(Path path); | ||
} | ||
|
||
private static final Provider NOOP_FILE_SYSTEM_NATIVES_PROVIDER = path -> OptionalLong.empty(); | ||
private static final Provider JNA_PROVIDER = loadJnaProvider(); | ||
|
||
private static Provider loadJnaProvider() { | ||
try { | ||
// load one of the main JNA classes to see if the classes are available. this does not ensure that all native | ||
// libraries are available, only the ones necessary by JNA to function | ||
Class.forName("com.sun.jna.Native"); | ||
if (Constants.WINDOWS) { | ||
return WindowsFileSystemNatives.getInstance(); | ||
} | ||
} catch (ClassNotFoundException e) { | ||
logger.warn("JNA not found. FileSystemNatives methods will be disabled.", e); | ||
} catch (LinkageError e) { | ||
logger.warn("unable to load JNA native support library, FileSystemNatives methods will be disabled.", e); | ||
} | ||
return NOOP_FILE_SYSTEM_NATIVES_PROVIDER; | ||
} | ||
ChrisHegarty marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private FileSystemNatives() {} | ||
|
||
public static void init() { | ||
assert JNA_PROVIDER != null; | ||
} | ||
|
||
/** | ||
* Returns the number of allocated bytes on disk for a given file. | ||
* | ||
* @param path the path to the file | ||
* @return an {@link OptionalLong} that contains the number of allocated bytes on disk for the file. The optional is empty is the | ||
* allocated size of the file failed be retrieved using native methods | ||
*/ | ||
public static OptionalLong allocatedSizeInBytes(Path path) { | ||
return JNA_PROVIDER.allocatedSizeInBytes(path); | ||
} | ||
|
||
} |
98 changes: 98 additions & 0 deletions
98
server/src/main/java/org/elasticsearch/common/filesystem/WindowsFileSystemNatives.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
package org.elasticsearch.common.filesystem; | ||
|
||
import com.sun.jna.Native; | ||
import com.sun.jna.WString; | ||
import com.sun.jna.ptr.IntByReference; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.lucene.util.Constants; | ||
|
||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.OptionalLong; | ||
|
||
/** | ||
* {@link FileSystemNatives.Provider} implementation for Windows/Kernel32 | ||
*/ | ||
final class WindowsFileSystemNatives implements FileSystemNatives.Provider { | ||
arteam marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private static final Logger logger = LogManager.getLogger(WindowsFileSystemNatives.class); | ||
|
||
private static final WindowsFileSystemNatives INSTANCE = new WindowsFileSystemNatives(); | ||
|
||
private static final int INVALID_FILE_SIZE = -1; | ||
private static final int NO_ERROR = 0; | ||
|
||
private WindowsFileSystemNatives() { | ||
assert Constants.WINDOWS : Constants.OS_NAME; | ||
try { | ||
Native.register("kernel32"); | ||
logger.debug("windows/Kernel32 library loaded"); | ||
} catch (LinkageError e) { | ||
logger.warn("unable to link Windows/Kernel32 library. native methods and handlers will be disabled.", e); | ||
throw e; | ||
} | ||
} | ||
ChrisHegarty marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
static WindowsFileSystemNatives getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
/** | ||
* Retrieves the actual number of bytes of disk storage used to store a specified file. | ||
* | ||
* https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getcompressedfilesizew | ||
* | ||
* @param lpFileName the path string | ||
* @param lpFileSizeHigh pointer to high-order DWORD for compressed file size (or null if not needed) | ||
* @return the low-order DWORD for compressed file siz | ||
*/ | ||
private native int GetCompressedFileSizeW(WString lpFileName, IntByReference lpFileSizeHigh); | ||
|
||
/** | ||
* Retrieves the actual number of bytes of disk storage used to store a specified file. If the file is located on a volume that supports | ||
* compression and the file is compressed, the value obtained is the compressed size of the specified file. If the file is located on a | ||
* volume that supports sparse files and the file is a sparse file, the value obtained is the sparse size of the specified file. | ||
* | ||
* This method uses Win32 DLL native method {@link #GetCompressedFileSizeW(WString, IntByReference)}. | ||
* | ||
* @param path the path to the file | ||
* @return an {@link OptionalLong} that contains the number of allocated bytes on disk for the file, or empty if the size is invalid | ||
*/ | ||
public OptionalLong allocatedSizeInBytes(Path path) { | ||
assert Files.isRegularFile(path) : path; | ||
final WString fileName = new WString("\\\\?\\" + path); | ||
final IntByReference lpFileSizeHigh = new IntByReference(); | ||
|
||
final int lpFileSizeLow = GetCompressedFileSizeW(fileName, lpFileSizeHigh); | ||
if (lpFileSizeLow == INVALID_FILE_SIZE) { | ||
final int err = Native.getLastError(); | ||
if (err != NO_ERROR) { | ||
logger.warn("error [{}] when executing native method GetCompressedFileSizeW for file [{}]", err, path); | ||
return OptionalLong.empty(); | ||
} | ||
} | ||
|
||
// convert lpFileSizeLow to unsigned long and combine with signed/shifted lpFileSizeHigh | ||
final long allocatedSize = (((long) lpFileSizeHigh.getValue()) << Integer.SIZE) | Integer.toUnsignedLong(lpFileSizeLow); | ||
if (logger.isTraceEnabled()) { | ||
logger.trace( | ||
"executing native method GetCompressedFileSizeW returned [high={}, low={}, allocated={}] for file [{}]", | ||
lpFileSizeHigh, | ||
lpFileSizeLow, | ||
allocatedSize, | ||
path | ||
); | ||
} | ||
return OptionalLong.of(allocatedSize); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.