From 538fb249b80693bf0917c2fc5ca7ef0e3d77ba39 Mon Sep 17 00:00:00 2001 From: Sari Sakse Dalum Date: Tue, 27 Jun 2023 14:01:30 +0200 Subject: [PATCH 1/4] Export `stat!` and `Base.Filesystem.get_stat_buf` and add to manual --- base/exports.jl | 1 + base/stat.jl | 1 + doc/src/base/file.md | 2 ++ 3 files changed, 4 insertions(+) diff --git a/base/exports.jl b/base/exports.jl index 10f43825e12df..c0a839b80688b 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -946,6 +946,7 @@ export rm, samefile, stat, + stat!, symlink, tempdir, tempname, diff --git a/base/stat.jl b/base/stat.jl index 84c5c33a5fdf7..255d7338c9cbc 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -23,6 +23,7 @@ export mtime, operm, stat, + stat!, uperm struct StatStruct diff --git a/doc/src/base/file.md b/doc/src/base/file.md index 9a9dc5d8a72f8..27203260b1086 100644 --- a/doc/src/base/file.md +++ b/doc/src/base/file.md @@ -15,8 +15,10 @@ Base.Filesystem.chmod Base.Filesystem.chown Base.RawFD Base.stat +Base.stat! Base.Filesystem.diskstat Base.Filesystem.lstat +Base.Filesystem.get_stat_buf Base.Filesystem.ctime Base.Filesystem.mtime Base.Filesystem.filemode From 36a29fe926d7c0afc42bb19c1c3b2564076e59e3 Mon Sep 17 00:00:00 2001 From: Sari Sakse Dalum Date: Tue, 27 Jun 2023 15:34:36 +0200 Subject: [PATCH 2/4] Resize buffer if too small and remove `get_stat_buf` --- base/stat.jl | 22 ++++++++++------------ doc/src/base/file.md | 1 - 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/base/stat.jl b/base/stat.jl index 255d7338c9cbc..8fff101f9aa5a 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -26,6 +26,8 @@ export stat!, uperm +const STAT_BUFFER_SIZE = Int(ccall(:jl_sizeof_stat, Int32, ())) + struct StatStruct desc :: Union{String, OS_HANDLE} # for show method, not included in equality or hash device :: UInt @@ -147,6 +149,7 @@ show(io::IO, ::MIME"text/plain", st::StatStruct) = show_statstruct(io, st, false macro stat_call!(stat_buf, sym, arg1type, arg) return quote + length($(esc(stat_buf))) < STAT_BUFFER_SIZE && resize!($(esc(stat_buf)), STAT_BUFFER_SIZE) r = ccall($(Expr(:quote, sym)), Int32, ($(esc(arg1type)), Ptr{UInt8}), $(esc(arg)), $(esc(stat_buf))) if !(r in (0, Base.UV_ENOENT, Base.UV_ENOTDIR, Base.UV_EINVAL)) uv_error(string("stat(", repr($(esc(arg))), ")"), r) @@ -162,9 +165,11 @@ end """ stat!(stat_buf::Vector{UInt8}, file) -Like [`stat`](@ref), but avoids internal allocations by using a pre-allocated buffer, -`stat_buf`. For a small performance gain over `stat`, consecutive calls to `stat!` can use -the same `stat_buf`. See also [`Base.Filesystem.get_stat_buf`](@ref). +Like [`stat`](@ref), but tries to avoid internal allocations by using a pre-allocated +buffer, `stat_buf`. For a small performance gain over `stat`, consecutive calls to `stat!` +can use the same `stat_buf`. If `stat_buf` is not large enough to hold the result, it will +be automatically resized. A buffer with the minimum capacity can be allocated using: +`Vector{UInt8}(undef, Base.Filesystem.STAT_BUFFER_SIZE)`. """ stat!(stat_buf::Vector{UInt8}, fd::OS_HANDLE) = @stat_call! stat_buf jl_fstat OS_HANDLE fd stat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_stat Cstring path @@ -174,15 +179,8 @@ if RawFD !== OS_HANDLE end stat!(stat_buf::Vector{UInt8}, fd::Integer) = stat!(stat_buf, RawFD(fd)) -stat(x) = stat!(get_stat_buf(), x) -lstat(x) = lstat!(get_stat_buf(), x) - -""" - get_stat_buf() - -Return a buffer of bytes of the right size for [`stat!`](@ref). -""" -get_stat_buf() = zeros(UInt8, Int(ccall(:jl_sizeof_stat, Int32, ()))) +stat(x) = stat!(Vector{UInt8}(undef, STAT_BUFFER_SIZE), x) +lstat(x) = lstat!(Vector{UInt8}(undef, STAT_BUFFER_SIZE), x) """ stat(file) diff --git a/doc/src/base/file.md b/doc/src/base/file.md index 27203260b1086..db7ba1a51b4ba 100644 --- a/doc/src/base/file.md +++ b/doc/src/base/file.md @@ -18,7 +18,6 @@ Base.stat Base.stat! Base.Filesystem.diskstat Base.Filesystem.lstat -Base.Filesystem.get_stat_buf Base.Filesystem.ctime Base.Filesystem.mtime Base.Filesystem.filemode From 15b285f73ff53ca7970a1cb3f1e87f812dbe025f Mon Sep 17 00:00:00 2001 From: Sari Sakse Dalum Date: Tue, 27 Jun 2023 15:36:50 +0200 Subject: [PATCH 3/4] Go back to zeros --- base/stat.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/stat.jl b/base/stat.jl index 8fff101f9aa5a..c697e0549e0b7 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -169,7 +169,7 @@ Like [`stat`](@ref), but tries to avoid internal allocations by using a pre-allo buffer, `stat_buf`. For a small performance gain over `stat`, consecutive calls to `stat!` can use the same `stat_buf`. If `stat_buf` is not large enough to hold the result, it will be automatically resized. A buffer with the minimum capacity can be allocated using: -`Vector{UInt8}(undef, Base.Filesystem.STAT_BUFFER_SIZE)`. +`zeros(UInt8, Base.Filesystem.STAT_BUFFER_SIZE)`. """ stat!(stat_buf::Vector{UInt8}, fd::OS_HANDLE) = @stat_call! stat_buf jl_fstat OS_HANDLE fd stat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_stat Cstring path @@ -179,8 +179,8 @@ if RawFD !== OS_HANDLE end stat!(stat_buf::Vector{UInt8}, fd::Integer) = stat!(stat_buf, RawFD(fd)) -stat(x) = stat!(Vector{UInt8}(undef, STAT_BUFFER_SIZE), x) -lstat(x) = lstat!(Vector{UInt8}(undef, STAT_BUFFER_SIZE), x) +stat(x) = stat!(zeros(UInt8, STAT_BUFFER_SIZE), x) +lstat(x) = lstat!(zeros(UInt8, STAT_BUFFER_SIZE), x) """ stat(file) From dd30113cc4dfe92f048803f9885302fa4b3fac26 Mon Sep 17 00:00:00 2001 From: Sari Sakse Dalum Date: Tue, 27 Jun 2023 15:45:03 +0200 Subject: [PATCH 4/4] Add tests --- test/file.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/file.jl b/test/file.jl index 1d2ac4c6f9132..a863e03117ffb 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1718,6 +1718,16 @@ end end end +@testset "stat! buffer resizing" begin + mktempdir() do dir + buf = UInt8[] + @test length(buf) < Base.Filesystem.STAT_BUFFER_SIZE + stat!(buf, dir) + @test length(buf) == Base.Filesystem.STAT_BUFFER_SIZE + @test iszero(@allocated stat!(buf, dir)) + end +end + @testset "diskstat() works" begin # Sanity check assuming disk is smaller than 32PB PB = Int64(2)^44