Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci.cmake83
-rw-r--r--.docs.cmake4
-rw-r--r--.gitmodules16
-rw-r--r--.travis.yml16
-rw-r--r--CMakeLists.txt66
-rw-r--r--CTestConfig.cmake2
-rw-r--r--Doxyfile34
-rw-r--r--Readme.md19
-rw-r--r--appveyor.yml8
-rw-r--r--cmake/headers.cmake158
-rw-r--r--cmake/interface.cmake4
-rw-r--r--cmake/sources.cmake4
-rw-r--r--cmake/tests.cmake11
m---------doc/html8
-rw-r--r--doc/presentations/videos.txt4
-rw-r--r--example/single-header.cpp8
-rw-r--r--example/ts_examples.cpp103
-rw-r--r--example/use_cases.cpp114
-rw-r--r--include/afio.hpp1
-rw-r--r--include/afio/afio.hpp22
-rw-r--r--include/afio/afio.ixx4
m---------include/afio/ntkernel-error-category0
-rw-r--r--include/afio/revision.hpp4
-rw-r--r--include/afio/v2.0/afio.hpp86
-rw-r--r--include/afio/v2.0/algorithm/mapped_span.hpp124
-rw-r--r--include/afio/v2.0/deadline.h112
m---------include/afio/v2.0/outcome0
m---------include/afio/v2.0/quickcpplib0
-rw-r--r--include/afio/version.hpp34
-rw-r--r--include/llfio.hpp1
-rw-r--r--include/llfio/llfio.hpp22
-rw-r--r--include/llfio/llfio.ixx4
-rw-r--r--include/llfio/revision.hpp4
-rw-r--r--include/llfio/v2.0/algorithm/cached_parent_handle_adapter.hpp (renamed from include/afio/v2.0/algorithm/cached_parent_handle_adapter.hpp)55
-rw-r--r--include/llfio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp (renamed from include/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp)49
-rw-r--r--include/llfio/v2.0/algorithm/shared_fs_mutex/base.hpp (renamed from include/afio/v2.0/algorithm/shared_fs_mutex/base.hpp)10
-rw-r--r--include/llfio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp (renamed from include/afio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp)20
-rw-r--r--include/llfio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp (renamed from include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp)20
-rw-r--r--include/llfio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp (renamed from include/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp)28
-rw-r--r--include/llfio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp (renamed from include/afio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp)28
-rw-r--r--include/llfio/v2.0/algorithm/trivial_vector.hpp (renamed from include/afio/v2.0/algorithm/trivial_vector.hpp)10
-rw-r--r--include/llfio/v2.0/async_file_handle.hpp (renamed from include/afio/v2.0/async_file_handle.hpp)74
-rw-r--r--include/llfio/v2.0/config.hpp (renamed from include/afio/v2.0/config.hpp)284
-rw-r--r--include/llfio/v2.0/deadline.h129
-rw-r--r--include/llfio/v2.0/detail/impl/cached_parent_handle_adapter.ipp (renamed from include/afio/v2.0/detail/impl/cached_parent_handle_adapter.ipp)10
-rw-r--r--include/llfio/v2.0/detail/impl/path_discovery.ipp (renamed from include/afio/v2.0/detail/impl/path_discovery.ipp)30
-rw-r--r--include/llfio/v2.0/detail/impl/posix/async_file_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/async_file_handle.ipp)62
-rw-r--r--include/llfio/v2.0/detail/impl/posix/directory_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/directory_handle.ipp)20
-rw-r--r--include/llfio/v2.0/detail/impl/posix/file_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/file_handle.ipp)30
-rw-r--r--include/llfio/v2.0/detail/impl/posix/fs_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/fs_handle.ipp)154
-rw-r--r--include/llfio/v2.0/detail/impl/posix/handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/handle.ipp)47
-rw-r--r--include/llfio/v2.0/detail/impl/posix/import.hpp (renamed from include/afio/v2.0/detail/impl/posix/import.hpp)8
-rw-r--r--include/llfio/v2.0/detail/impl/posix/io_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/io_handle.ipp)51
-rw-r--r--include/llfio/v2.0/detail/impl/posix/io_service.ipp (renamed from include/afio/v2.0/detail/impl/posix/io_service.ipp)30
-rw-r--r--include/llfio/v2.0/detail/impl/posix/map_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/map_handle.ipp)123
-rw-r--r--include/llfio/v2.0/detail/impl/posix/mapped_file_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp)12
-rw-r--r--include/llfio/v2.0/detail/impl/posix/path_discovery.ipp (renamed from include/afio/v2.0/detail/impl/posix/path_discovery.ipp)12
-rw-r--r--include/llfio/v2.0/detail/impl/posix/path_handle.ipp (renamed from include/afio/v2.0/detail/impl/posix/path_handle.ipp)6
-rw-r--r--include/llfio/v2.0/detail/impl/posix/stat.ipp (renamed from include/afio/v2.0/detail/impl/posix/stat.ipp)20
-rw-r--r--include/llfio/v2.0/detail/impl/posix/statfs.ipp (renamed from include/afio/v2.0/detail/impl/posix/statfs.ipp)8
-rw-r--r--include/llfio/v2.0/detail/impl/posix/storage_profile.ipp (renamed from include/afio/v2.0/detail/impl/posix/storage_profile.ipp)4
-rw-r--r--include/llfio/v2.0/detail/impl/posix/symlink_handle.ipp468
-rw-r--r--include/llfio/v2.0/detail/impl/posix/utils.ipp (renamed from include/afio/v2.0/detail/impl/posix/utils.ipp)10
-rw-r--r--include/llfio/v2.0/detail/impl/safe_byte_ranges.ipp (renamed from include/afio/v2.0/detail/impl/safe_byte_ranges.ipp)16
-rw-r--r--include/llfio/v2.0/detail/impl/storage_profile.ipp (renamed from include/afio/v2.0/detail/impl/storage_profile.ipp)28
-rw-r--r--include/llfio/v2.0/detail/impl/windows/async_file_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/async_file_handle.ipp)34
-rw-r--r--include/llfio/v2.0/detail/impl/windows/directory_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/directory_handle.ipp)66
-rw-r--r--include/llfio/v2.0/detail/impl/windows/file_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/file_handle.ipp)83
-rw-r--r--include/llfio/v2.0/detail/impl/windows/fs_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/fs_handle.ipp)23
-rw-r--r--include/llfio/v2.0/detail/impl/windows/handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/handle.ipp)22
-rw-r--r--include/llfio/v2.0/detail/impl/windows/import.hpp (renamed from include/afio/v2.0/detail/impl/windows/import.hpp)104
-rw-r--r--include/llfio/v2.0/detail/impl/windows/io_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/io_handle.ipp)38
-rw-r--r--include/llfio/v2.0/detail/impl/windows/io_service.ipp (renamed from include/afio/v2.0/detail/impl/windows/io_service.ipp)12
-rw-r--r--include/llfio/v2.0/detail/impl/windows/map_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/map_handle.ipp)113
-rw-r--r--include/llfio/v2.0/detail/impl/windows/mapped_file_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/mapped_file_handle.ipp)16
-rw-r--r--include/llfio/v2.0/detail/impl/windows/path_discovery.ipp (renamed from include/afio/v2.0/detail/impl/windows/path_discovery.ipp)6
-rw-r--r--include/llfio/v2.0/detail/impl/windows/path_handle.ipp (renamed from include/afio/v2.0/detail/impl/windows/path_handle.ipp)6
-rw-r--r--include/llfio/v2.0/detail/impl/windows/path_view.ipp (renamed from include/afio/v2.0/detail/impl/windows/path_view.ipp)8
-rw-r--r--include/llfio/v2.0/detail/impl/windows/stat.ipp (renamed from include/afio/v2.0/detail/impl/windows/stat.ipp)8
-rw-r--r--include/llfio/v2.0/detail/impl/windows/statfs.ipp (renamed from include/afio/v2.0/detail/impl/windows/statfs.ipp)8
-rw-r--r--include/llfio/v2.0/detail/impl/windows/storage_profile.ipp (renamed from include/afio/v2.0/detail/impl/windows/storage_profile.ipp)4
-rw-r--r--include/llfio/v2.0/detail/impl/windows/symlink_handle.ipp283
-rw-r--r--include/llfio/v2.0/detail/impl/windows/utils.ipp (renamed from include/afio/v2.0/detail/impl/windows/utils.ipp)12
-rw-r--r--include/llfio/v2.0/directory_handle.hpp (renamed from include/afio/v2.0/directory_handle.hpp)63
-rw-r--r--include/llfio/v2.0/file_handle.hpp (renamed from include/afio/v2.0/file_handle.hpp)71
-rw-r--r--include/llfio/v2.0/fs_handle.hpp (renamed from include/afio/v2.0/fs_handle.hpp)33
-rw-r--r--include/llfio/v2.0/handle.hpp (renamed from include/afio/v2.0/handle.hpp)96
-rw-r--r--include/llfio/v2.0/io_handle.hpp (renamed from include/afio/v2.0/io_handle.hpp)129
-rw-r--r--include/llfio/v2.0/io_service.hpp (renamed from include/afio/v2.0/io_service.hpp)94
-rw-r--r--include/llfio/v2.0/llfio.hpp86
-rw-r--r--include/llfio/v2.0/logging.hpp (renamed from include/afio/v2.0/logging.hpp)160
-rw-r--r--include/llfio/v2.0/map_handle.hpp (renamed from include/afio/v2.0/map_handle.hpp)115
-rw-r--r--include/llfio/v2.0/map_view.hpp87
-rw-r--r--include/llfio/v2.0/mapped.hpp136
-rw-r--r--include/llfio/v2.0/mapped_file_handle.hpp (renamed from include/afio/v2.0/mapped_file_handle.hpp)54
-rw-r--r--include/llfio/v2.0/native_handle_type.hpp (renamed from include/afio/v2.0/native_handle_type.hpp)16
m---------include/llfio/v2.0/outcome0
-rw-r--r--include/llfio/v2.0/path_discovery.hpp (renamed from include/afio/v2.0/path_discovery.hpp)20
-rw-r--r--include/llfio/v2.0/path_handle.hpp (renamed from include/afio/v2.0/path_handle.hpp)69
-rw-r--r--include/llfio/v2.0/path_view.hpp (renamed from include/afio/v2.0/path_view.hpp)246
m---------include/llfio/v2.0/quickcpplib0
-rw-r--r--include/llfio/v2.0/stat.hpp (renamed from include/afio/v2.0/stat.hpp)20
-rw-r--r--include/llfio/v2.0/statfs.hpp (renamed from include/afio/v2.0/statfs.hpp)22
-rw-r--r--include/llfio/v2.0/status_code.hpp (renamed from include/afio/v2.0/status_code.hpp)168
-rw-r--r--include/llfio/v2.0/storage_profile.hpp (renamed from include/afio/v2.0/storage_profile.hpp)94
-rw-r--r--include/llfio/v2.0/symlink_handle.hpp494
-rw-r--r--include/llfio/v2.0/utils.hpp (renamed from include/afio/v2.0/utils.hpp)41
-rw-r--r--include/llfio/version.hpp34
-rw-r--r--meta/libraries.json4
-rw-r--r--programs/CMakeLists.txt14
-rw-r--r--programs/benchmark-iostreams/main.cpp36
-rw-r--r--programs/benchmark-locking/main.cpp48
-rw-r--r--programs/fs-probe/main.cpp10
-rw-r--r--programs/key-value-store/Readme.md6
-rw-r--r--programs/key-value-store/include/key_value_store.hpp114
-rw-r--r--programs/key-value-store/main.cpp32
-rw-r--r--release_notes.md53
-rw-r--r--scripts/make_free_functions.py16
-rw-r--r--src/afio.cpp3
-rw-r--r--src/llfio.cpp3
m---------test/kerneltest0
-rw-r--r--test/test_kernel_decl.hpp31
-rw-r--r--test/tests/async_io.cpp28
-rw-r--r--test/tests/coroutines.cpp24
-rw-r--r--test/tests/current_path.cpp22
-rw-r--r--test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp22
-rw-r--r--test/tests/directory_handle_create_close/runner.cpp16
-rw-r--r--test/tests/directory_handle_enumerate/kernel_directory_handle_enumerate.cpp.hpp4
-rw-r--r--test/tests/directory_handle_enumerate/runner.cpp16
-rw-r--r--test/tests/file_handle_create_close/kernel_async_file_handle.cpp.hpp14
-rw-r--r--test/tests/file_handle_create_close/kernel_file_handle.cpp.hpp10
-rw-r--r--test/tests/file_handle_create_close/runner.cpp16
-rw-r--r--test/tests/file_handle_lock_unlock.cpp14
-rw-r--r--test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp6
-rw-r--r--test/tests/map_handle_create_close/runner.cpp28
-rw-r--r--test/tests/mapped.cpp (renamed from test/tests/mapped_span.cpp)38
-rw-r--r--test/tests/path_discovery.cpp12
-rw-r--r--test/tests/path_view.cpp109
-rw-r--r--test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp4
-rw-r--r--test/tests/section_handle_create_close/runner.cpp10
-rw-r--r--test/tests/shared_fs_mutex.cpp92
-rw-r--r--test/tests/symlink_handle_create_close/existing0/testfile.txt1
-rw-r--r--test/tests/symlink_handle_create_close/existing1/testfile.txt1
l---------test/tests/symlink_handle_create_close/existing1/testlink1
-rw-r--r--test/tests/symlink_handle_create_close/kernel_symlink_handle.cpp.hpp57
-rw-r--r--test/tests/symlink_handle_create_close/runner.cpp82
-rw-r--r--test/tests/trivial_vector.cpp24
147 files changed, 4553 insertions, 2598 deletions
diff --git a/.ci.cmake b/.ci.cmake
index 90aa9e1b..2a2b0962 100644
--- a/.ci.cmake
+++ b/.ci.cmake
@@ -5,7 +5,7 @@ include(cmake/QuickCppLibBootstrap.cmake)
include(QuickCppLibUtils)
-CONFIGURE_CTEST_SCRIPT_FOR_CDASH("afio" "prebuilt")
+CONFIGURE_CTEST_SCRIPT_FOR_CDASH("llfio" "prebuilt")
ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY})
include(FindGit)
set(CTEST_GIT_COMMAND "${GIT_EXECUTABLE}")
@@ -15,62 +15,67 @@ ctest_update()
ctest_configure(OPTIONS ${CTEST_CONFIGURE_OPTIONS})
ctest_build(TARGET _dl)
ctest_build(TARGET _sl)
-ctest_test(RETURN_VALUE retval EXCLUDE "afio_hl|shared_fs_mutex")
if(WIN32)
- if(EXISTS "prebuilt/bin/Release/afio_dl-2.0-Windows-x64-Release.dll")
+ # Appveyor's Windows version doesn't permit unprivileged creation of symbolic links
+ ctest_test(RETURN_VALUE retval EXCLUDE "llfio_hl|shared_fs_mutex|symlink")
+else()
+ ctest_test(RETURN_VALUE retval EXCLUDE "llfio_hl|shared_fs_mutex")
+endif()
+if(WIN32)
+ if(EXISTS "prebuilt/bin/Release/llfio_dl-2.0-Windows-x64-Release.dll")
checked_execute_process("Tarring up binaries 1"
- COMMAND "${CMAKE_COMMAND}" -E make_directory afio/prebuilt/bin/Release
- COMMAND "${CMAKE_COMMAND}" -E make_directory afio/prebuilt/lib/Release
- COMMAND xcopy doc afio\\doc\\ /s /q
- COMMAND xcopy include afio\\include\\ /s /q
+ COMMAND "${CMAKE_COMMAND}" -E make_directory llfio/prebuilt/bin/Release
+ COMMAND "${CMAKE_COMMAND}" -E make_directory llfio/prebuilt/lib/Release
+ COMMAND xcopy doc llfio\\doc\\ /s /q
+ COMMAND xcopy include llfio\\include\\ /s /q
)
checked_execute_process("Tarring up binaries 2"
- COMMAND "${CMAKE_COMMAND}" -E copy Readme.md afio/
- COMMAND "${CMAKE_COMMAND}" -E copy release_notes.md afio/
+ COMMAND "${CMAKE_COMMAND}" -E copy Readme.md llfio/
+ COMMAND "${CMAKE_COMMAND}" -E copy release_notes.md llfio/
)
checked_execute_process("Tarring up binaries 3"
- COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/afio_sl-2.0-Windows-x64-Release.lib afio/prebuilt/lib/Release/
- COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/ntkernel-error-category_sl.lib afio/prebuilt/lib/Release/
+ COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/llfio_sl-2.0-Windows-x64-Release.lib llfio/prebuilt/lib/Release/
+ COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/ntkernel-error-category_sl.lib llfio/prebuilt/lib/Release/
)
checked_execute_process("Tarring up binaries 4"
- COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/afio_dl-2.0-Windows-x64-Release.lib afio/prebuilt/lib/Release/
- COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/ntkernel-error-category_dl.lib afio/prebuilt/lib/Release/
+ COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/llfio_dl-2.0-Windows-x64-Release.lib llfio/prebuilt/lib/Release/
+ COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/lib/Release/ntkernel-error-category_dl.lib llfio/prebuilt/lib/Release/
)
checked_execute_process("Tarring up binaries 5"
- COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/bin/Release/afio_dl-2.0-Windows-x64-Release.dll afio/prebuilt/bin/Release/
- COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/bin/Release/ntkernel-error-category_dl.dll afio/prebuilt/bin/Release/
+ COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/bin/Release/llfio_dl-2.0-Windows-x64-Release.dll llfio/prebuilt/bin/Release/
+ COMMAND "${CMAKE_COMMAND}" -E copy prebuilt/bin/Release/ntkernel-error-category_dl.dll llfio/prebuilt/bin/Release/
)
checked_execute_process("Tarring up binaries final"
- COMMAND 7z a -tzip afio-v2.0-binaries-win64.zip afio\\
+ COMMAND 7z a -tzip llfio-v2.0-binaries-win64.zip llfio\\
)
- get_filename_component(toupload afio-v2.0-binaries-win64.zip ABSOLUTE)
+ get_filename_component(toupload llfio-v2.0-binaries-win64.zip ABSOLUTE)
endif()
else()
- if(EXISTS "prebuilt/lib/libafio_dl-2.0-Linux-x86_64-Release.so")
+ if(EXISTS "prebuilt/lib/libllfio_dl-2.0-Linux-x86_64-Release.so")
checked_execute_process("Tarring up binaries"
- COMMAND mkdir afio
- COMMAND cp -a doc afio/
- COMMAND cp -a include afio/
- COMMAND cp -a Readme.md afio/
- COMMAND cp -a release_notes.md afio/
- COMMAND cp -a --parents prebuilt/lib/libafio_sl-2.0-Linux-x86_64-Release.a afio/
- COMMAND cp -a --parents prebuilt/lib/libafio_dl-2.0-Linux-x86_64-Release.so afio/
- COMMAND "${CMAKE_COMMAND}" -E tar cfz afio-v2.0-binaries-linux64.tgz afio
+ COMMAND mkdir llfio
+ COMMAND cp -a doc llfio/
+ COMMAND cp -a include llfio/
+ COMMAND cp -a Readme.md llfio/
+ COMMAND cp -a release_notes.md llfio/
+ COMMAND cp -a --parents prebuilt/lib/libllfio_sl-2.0-Linux-x86_64-Release.a llfio/
+ COMMAND cp -a --parents prebuilt/lib/libllfio_dl-2.0-Linux-x86_64-Release.so llfio/
+ COMMAND "${CMAKE_COMMAND}" -E tar cfz llfio-v2.0-binaries-linux64.tgz llfio
)
- get_filename_component(toupload afio-v2.0-binaries-linux64.tgz ABSOLUTE)
+ get_filename_component(toupload llfio-v2.0-binaries-linux64.tgz ABSOLUTE)
endif()
- if(EXISTS "prebuilt/lib/libafio_dl-2.0-Darwin-x86_64-Release.so")
+ if(EXISTS "prebuilt/lib/libllfio_dl-2.0-Darwin-x86_64-Release.so")
checked_execute_process("Tarring up binaries"
- COMMAND mkdir afio
- COMMAND cp -a doc afio/
- COMMAND cp -a include afio/
- COMMAND cp -a Readme.md afio/
- COMMAND cp -a release_notes.md afio/
- COMMAND cp -a --parents prebuilt/lib/libafio_sl-2.0-Darwin-x86_64-Release.a afio/
- COMMAND cp -a --parents prebuilt/lib/libafio_dl-2.0-Darwin-x86_64-Release.dylib afio/
- COMMAND "${CMAKE_COMMAND}" -E tar cfz afio-v2.0-binaries-darwin64.tgz afio
+ COMMAND mkdir llfio
+ COMMAND cp -a doc llfio/
+ COMMAND cp -a include llfio/
+ COMMAND cp -a Readme.md llfio/
+ COMMAND cp -a release_notes.md llfio/
+ COMMAND cp -a --parents prebuilt/lib/libllfio_sl-2.0-Darwin-x86_64-Release.a llfio/
+ COMMAND cp -a --parents prebuilt/lib/libllfio_dl-2.0-Darwin-x86_64-Release.dylib llfio/
+ COMMAND "${CMAKE_COMMAND}" -E tar cfz llfio-v2.0-binaries-darwin64.tgz llfio
)
- get_filename_component(toupload afio-v2.0-binaries-darwin64.tgz ABSOLUTE)
+ get_filename_component(toupload llfio-v2.0-binaries-darwin64.tgz ABSOLUTE)
endif()
endif()
set(retval2 0)
@@ -79,13 +84,13 @@ if(("$ENV{CXX}" MATCHES "clang") OR ("$ENV{CXX}" MATCHES "g\\+\\+"))
if("$ENV{CXX}" MATCHES "clang")
ctest_build(TARGET _sl-asan)
set(CTEST_CONFIGURATION_TYPE "asan")
- ctest_test(RETURN_VALUE retval2 INCLUDE "afio_sl" EXCLUDE "shared_fs_mutex")
+ ctest_test(RETURN_VALUE retval2 INCLUDE "llfio_sl" EXCLUDE "shared_fs_mutex")
else()
set(retval2 0)
endif()
ctest_build(TARGET _sl-ubsan)
set(CTEST_CONFIGURATION_TYPE "ubsan")
- ctest_test(RETURN_VALUE retval3 INCLUDE "afio_sl" EXCLUDE "shared_fs_mutex")
+ ctest_test(RETURN_VALUE retval3 INCLUDE "llfio_sl" EXCLUDE "shared_fs_mutex")
endif()
merge_junit_results_into_ctest_xml()
if(EXISTS "${toupload}")
diff --git a/.docs.cmake b/.docs.cmake
index 9348195c..8763e385 100644
--- a/.docs.cmake
+++ b/.docs.cmake
@@ -4,7 +4,7 @@ include(cmake/QuickCppLibBootstrap.cmake)
include(QuickCppLibUtils)
-CONFIGURE_CTEST_SCRIPT_FOR_CDASH("afio" "cmake_ci")
+CONFIGURE_CTEST_SCRIPT_FOR_CDASH("llfio" "cmake_ci")
ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY})
include(FindGit)
set(CTEST_GIT_COMMAND "${GIT_EXECUTABLE}")
@@ -21,7 +21,7 @@ checked_execute_process("git reset"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/doc/html"
)
ctest_configure()
-ctest_build(TARGET afio_docs)
+ctest_build(TARGET llfio_docs)
#checked_execute_process("git commit"
# COMMAND "${GIT_EXECUTABLE}" commit -a -m "upd"
# COMMAND "${GIT_EXECUTABLE}" push -f origin gh-pages
diff --git a/.gitmodules b/.gitmodules
index 9b1bbb47..c3fb6f14 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,12 +1,12 @@
[submodule "doc/html"]
path = doc/html
- url = https://github.com/ned14/afio.git
+ url = https://github.com/ned14/llfio.git
branch = gh-pages
fetchRecurseSubmodules = true
ignore = none
# shallow = true
-[submodule "include/afio/v2.0/outcome"]
- path = include/afio/v2.0/outcome
+[submodule "include/llfio/v2.0/outcome"]
+ path = include/llfio/v2.0/outcome
url = https://github.com/ned14/outcome.git
branch = master
fetchRecurseSubmodules = true
@@ -19,16 +19,10 @@
fetchRecurseSubmodules = true
ignore = untracked
# shallow = true
-[submodule "include/afio/v2.0/quickcpplib"]
- path = include/afio/v2.0/quickcpplib
+[submodule "include/llfio/v2.0/quickcpplib"]
+ path = include/llfio/v2.0/quickcpplib
url = https://github.com/ned14/quickcpplib
branch = master
fetchRecurseSubmodules = true
ignore = untracked
# shallow = true
-[submodule "include/afio/ntkernel-error-category"]
- path = include/afio/ntkernel-error-category
- url = https://github.com/ned14/ntkernel-error-category.git
- branch = master
- fetchRecurseSubmodules = true
- ignore = untracked
diff --git a/.travis.yml b/.travis.yml
index 84d65b19..03e29834 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,7 +35,7 @@ env:
- secure: "A3TeWTlJdjUaQ31NF60kMOik8mzaJkdKA55jZXjN83BJ2ZjMDmWfq1XmZ7iDIxmn7HC2BVpjhdkj9jpRtPztb08L5VSlJIiVbXlBWNwgzmYANujpR9rA+bhZJwlKDaYQHUZUd4+iGHCHb0dLt2HG0eHF5azaifd0YqCfz5GcWl8="
matrix:
- __="cmake tests (error_code)" NAME=TravisLinuxWorkerEC CMAKE_CONFIGURE_OPTIONS=
- - __="cmake tests (status_code)" NAME=TravisLinuxWorkerSC CMAKE_CONFIGURE_OPTIONS=-DAFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE=ON
+ - __="cmake tests (status_code)" NAME=TravisLinuxWorkerSC CMAKE_CONFIGURE_OPTIONS=-DLLFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE=ON
# - __="cmake tests" NAME=TravisOSXWorker
- __="Documentation" NAME=TravisDocumentation
- __="Programs"
@@ -49,7 +49,7 @@ matrix:
# - os: osx
# env: __="cmake tests (error_code)" NAME=TravisLinuxWorkerEC CMAKE_CONFIGURE_OPTIONS=
# - os: osx
-# env: __="cmake tests (status_code)" NAME=TravisLinuxWorkerSC CMAKE_CONFIGURE_OPTIONS=-DAFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE=ON
+# env: __="cmake tests (status_code)" NAME=TravisLinuxWorkerSC CMAKE_CONFIGURE_OPTIONS=-DLLFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE=ON
- os: linux
compiler: g++
env: __="Documentation" NAME=TravisDocumentation
@@ -104,7 +104,7 @@ script:
cd doc/html;
git add . || true;
git commit -a -m "Travis CI updates documentation" || true;
- git push -f https://jenkins-nedprod:$JENKINS_NEDPROD_PASSWORD@github.com/ned14/boost.afio gh-pages;
+ git push -f https://jenkins-nedprod:$JENKINS_NEDPROD_PASSWORD@github.com/ned14/llfio gh-pages;
cd ../..;
fi
-
@@ -118,15 +118,15 @@ script:
after_success:
# - bash -x ./update_coveralls.sh `pwd`
-# - NEWNAME=afio-v2.0-binaries-linux64-$(date +%Y%m%d%H%M%S).tgz
+# - NEWNAME=llfio-v2.0-binaries-linux64-$(date +%Y%m%d%H%M%S).tgz
- if [ "${TRAVIS_OS_NAME}" = "linux" ] && [ "$CXX" = "clang++-4.0" ] && [ "$__" = "cmake tests (error_code)" ]; then
- NEWNAME=afio-v2.0-binaries-linux64-$TRAVIS_COMMIT.tgz;
- mv afio-v2.0-binaries-linux64.tgz $NEWNAME;
+ NEWNAME=llfio-v2.0-binaries-linux64-$TRAVIS_COMMIT.tgz;
+ mv llfio-v2.0-binaries-linux64.tgz $NEWNAME;
curl -T $NEWNAME -u jenkins-nedprod:$JENKINS_NEDPROD_PASSWORD https://dedi5.nedprod.com/static/files/upload/;
fi
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
- NEWNAME=afio-v2.0-binaries-darwin64-$TRAVIS_COMMIT.tgz;
- mv afio-v2.0-binaries-darwin64.tgz $NEWNAME;
+ NEWNAME=llfio-v2.0-binaries-darwin64-$TRAVIS_COMMIT.tgz;
+ mv llfio-v2.0-binaries-darwin64.tgz $NEWNAME;
curl -T $NEWNAME -u jenkins-nedprod:$JENKINS_NEDPROD_PASSWORD https://dedi5.nedprod.com/static/files/upload/;
fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 66405cc6..55a177ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,26 +4,26 @@ include(QuickCppLibRequireOutOfSourceBuild)
include(QuickCppLibUtils)
include(QuickCppLibPolicies)
-option(AFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE "Whether to use SG14 status_code for failure handling" OFF)
+option(LLFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE "Whether to use SG14 status_code for failure handling" OFF)
# Parse the version we tell cmake directly from the version header file
-ParseProjectVersionFromHpp("${CMAKE_CURRENT_SOURCE_DIR}/include/afio/version.hpp" VERSIONSTRING)
+ParseProjectVersionFromHpp("${CMAKE_CURRENT_SOURCE_DIR}/include/llfio/version.hpp" VERSIONSTRING)
# Sets the usual PROJECT_NAME etc
-project(afio VERSION ${VERSIONSTRING} LANGUAGES C CXX)
+project(llfio VERSION ${VERSIONSTRING} LANGUAGES C CXX)
# Also set a *cmake* namespace for this project
set(PROJECT_NAMESPACE)
# Setup this cmake environment for this project
include(QuickCppLibSetupProject)
if(NOT PROJECT_IS_DEPENDENCY)
# This file should be updated with the last git SHA next commit
- UpdateRevisionHppFromGit("${CMAKE_CURRENT_SOURCE_DIR}/include/afio/revision.hpp")
+ UpdateRevisionHppFromGit("${CMAKE_CURRENT_SOURCE_DIR}/include/llfio/revision.hpp")
endif()
# Find my library dependencies
find_quickcpplib_library(quickcpplib 1.0 REQUIRED)
find_quickcpplib_library(outcome 2.0 REQUIRED)
find_quickcpplib_library(kerneltest 1.0 REQUIRED)
if(WIN32)
- add_subdirectory("include/afio/ntkernel-error-category" EXCLUDE_FROM_ALL)
+ add_subdirectory("include/llfio/ntkernel-error-category" EXCLUDE_FROM_ALL)
endif()
# Make the standard static and shared libraries, and if supported by this compiler, C++ modules
@@ -65,28 +65,28 @@ if(NOT PROJECT_IS_DEPENDENCY)
add_dependencies(outcome_hl ${target})
endif()
endfunction()
- make_single_header(afio_hl-pp-posix
- "${CMAKE_CURRENT_SOURCE_DIR}/single-header/afio-posix.hpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/include/afio/v2.0/afio.hpp"
+ make_single_header(llfio_hl-pp-posix
+ "${CMAKE_CURRENT_SOURCE_DIR}/single-header/llfio-posix.hpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/llfio/v2.0/llfio.hpp"
#-D QUICKCPPLIB_USE_STD_BYTE -D QUICKCPPLIB_USE_STD_OPTIONAL -D QUICKCPPLIB_USE_STD_SPAN
-U gsl_COMPILER_MSVC_VERSION -U gsl_HAS_CPP0X -D gsl_CPLUSPLUS=201703 -D __cplusplus=201703
- -D AFIO_LEAN_AND_MEAN -U _WIN32
- -D AFIO_EXPERIMENTAL_STATUS_CODE=1)
- make_single_header(afio_hl-pp-win
- "${CMAKE_CURRENT_SOURCE_DIR}/single-header/afio-win.hpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/include/afio/v2.0/afio.hpp"
+ -D LLFIO_LEAN_AND_MEAN -U _WIN32
+ -D LLFIO_EXPERIMENTAL_STATUS_CODE=1)
+ make_single_header(llfio_hl-pp-win
+ "${CMAKE_CURRENT_SOURCE_DIR}/single-header/llfio-win.hpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/llfio/v2.0/llfio.hpp"
#-D QUICKCPPLIB_USE_STD_BYTE -D QUICKCPPLIB_USE_STD_OPTIONAL -D QUICKCPPLIB_USE_STD_SPAN
-D gsl_CPLUSPLUS=201703 -D __cplusplus=201703
- -D AFIO_LEAN_AND_MEAN -D _WIN32
- -D AFIO_EXPERIMENTAL_STATUS_CODE=1)
- make_single_header(afio_hl-pp-abi
+ -D LLFIO_LEAN_AND_MEAN -D _WIN32
+ -D LLFIO_EXPERIMENTAL_STATUS_CODE=1)
+ make_single_header(llfio_hl-pp-abi
"${CMAKE_CURRENT_SOURCE_DIR}/single-header/abi.hpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/include/afio/v2.0/afio.hpp"
- -D AFIO_EXPERIMENTAL_STATUS_CODE=1
- -D AFIO_DISABLE_ABI_PERMUTATION=1
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/llfio/v2.0/llfio.hpp"
+ -D LLFIO_EXPERIMENTAL_STATUS_CODE=1
+ -D LLFIO_DISABLE_ABI_PERMUTATION=1
-D OUTCOME_DISABLE_ABI_PERMUTATION=1
-D QUICKCPPLIB_DISABLE_ABI_PERMUTATION=1
- -U AFIO_UNSTABLE_VERSION
+ -U LLFIO_UNSTABLE_VERSION
-U OUTCOME_UNSTABLE_VERSION)
endif()
endif()
@@ -153,22 +153,22 @@ if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR APPLE)
all_link_libraries(PUBLIC ${libcxx_cxxexperimental})
endif()
# Set any macros this library requires
-if(AFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE)
- all_compile_definitions(PUBLIC AFIO_EXPERIMENTAL_STATUS_CODE=1)
+if(LLFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE)
+ all_compile_definitions(PUBLIC LLFIO_EXPERIMENTAL_STATUS_CODE=1)
endif()
if(WIN32)
all_compile_definitions(PRIVATE _WIN32_WINNT=0x600) ## Target WinVista
- if(NOT AFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE)
- target_link_libraries(afio_dl PUBLIC ntkernel-error-category::dl)
- target_link_libraries(afio_sl PUBLIC ntkernel-error-category::sl)
+ if(NOT LLFIO_USE_EXPERIMENTAL_SG14_STATUS_CODE)
+ target_link_libraries(llfio_dl PUBLIC ntkernel-error-category::dl)
+ target_link_libraries(llfio_sl PUBLIC ntkernel-error-category::sl)
endif()
endif()
# Anyone using the static or dynamic libraries is not using the header only variant
-foreach(lib afio_sl afio_dl)
- target_compile_definitions(${lib} INTERFACE AFIO_HEADERS_ONLY=0)
- target_compile_definitions(${lib} PRIVATE AFIO_SOURCE=1)
+foreach(lib llfio_sl llfio_dl)
+ target_compile_definitions(${lib} INTERFACE LLFIO_HEADERS_ONLY=0)
+ target_compile_definitions(${lib} PRIVATE LLFIO_SOURCE=1)
endforeach()
-if(TARGET afio-example_single-header)
+if(TARGET llfio-example_single-header)
set(compiler_has_cxx_17 0)
foreach(feature ${CMAKE_CXX_COMPILE_FEATURES})
if(feature STREQUAL "cxx_std_17")
@@ -177,20 +177,20 @@ if(TARGET afio-example_single-header)
endforeach()
# The single header test requires C++ 17
if(compiler_has_cxx_17)
- target_compile_features(afio-example_single-header PRIVATE cxx_std_17)
+ target_compile_features(llfio-example_single-header PRIVATE cxx_std_17)
else()
- set_target_properties(afio-example_single-header PROPERTIES EXCLUDE_FROM_ALL ON EXCLUDE_FROM_DEFAULT_BUILD ON)
+ set_target_properties(llfio-example_single-header PROPERTIES EXCLUDE_FROM_ALL ON EXCLUDE_FROM_DEFAULT_BUILD ON)
endif()
endif()
# For all possible configurations of this library, add each test
include(QuickCppLibMakeStandardTests)
# For each test target, link to kerneltest
-foreach(test_target ${afio_TEST_TARGETS})
+foreach(test_target ${llfio_TEST_TARGETS})
target_link_libraries(${test_target} PRIVATE kerneltest::hl)
endforeach()
if(MSVC)
- foreach(test_target ${afio_TEST_TARGETS})
+ foreach(test_target ${llfio_TEST_TARGETS})
target_compile_options(${test_target} PRIVATE /wd4503) ## decorated name length exceeded
endforeach()
endif()
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
index 1c2cca41..75616d63 100644
--- a/CTestConfig.cmake
+++ b/CTestConfig.cmake
@@ -6,7 +6,7 @@
## ENABLE_TESTING()
## INCLUDE(CTest)
-set(CTEST_PROJECT_NAME "AFIO")
+set(CTEST_PROJECT_NAME "LLFIO")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
set(CTEST_DROP_METHOD "http")
diff --git a/Doxyfile b/Doxyfile
index 258ed375..e1ac0a68 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = "AFIO"
+PROJECT_NAME = "LLFIO"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
@@ -768,10 +768,10 @@ WARN_LOGFILE = doxygen_warnings.log
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-INPUT = include/afio \
- include/afio/v2.0 \
- include/afio/v2.0/algorithm \
- include/afio/v2.0/algorithm/shared_fs_mutex \
+INPUT = include/llfio \
+ include/llfio/v2.0 \
+ include/llfio/v2.0/algorithm \
+ include/llfio/v2.0/algorithm/shared_fs_mutex \
release_notes.md
# This tag can be used to specify the character encoding of the source files
@@ -1223,7 +1223,7 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_BUNDLE_ID = org.doxygen.boostafio
+DOCSET_BUNDLE_ID = org.doxygen.boostllfio
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
@@ -1231,7 +1231,7 @@ DOCSET_BUNDLE_ID = org.doxygen.boostafio
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_PUBLISHER_ID = org.doxygen.boostafio
+DOCSET_PUBLISHER_ID = org.doxygen.boostllfio
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
@@ -1322,7 +1322,7 @@ QCH_FILE =
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_NAMESPACE = org.doxygen.boostafio
+QHP_NAMESPACE = org.doxygen.boostllfio
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
@@ -1381,7 +1381,7 @@ GENERATE_ECLIPSEHELP = NO
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
-ECLIPSE_DOC_ID = org.doxygen.boostafio
+ECLIPSE_DOC_ID = org.doxygen.boostllfio
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
@@ -2022,7 +2022,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-PREDEFINED = DOXYGEN_IS_IN_THE_HOUSE=1 DOXYGEN_SHOULD_SKIP_THIS=1 AFIO_REQUIRES(...)=
+PREDEFINED = DOXYGEN_IS_IN_THE_HOUSE=1 DOXYGEN_SHOULD_SKIP_THIS=1 LLFIO_REQUIRES(...)=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@@ -2031,14 +2031,14 @@ PREDEFINED = DOXYGEN_IS_IN_THE_HOUSE=1 DOXYGEN_SHOULD_SKIP_THIS=1 AF
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_AS_DEFINED = AFIO_DECL AFIO_DEADLINE_NAME AFIO_MAKE_FREE_FUNCTION \
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC AFIO_HEADERS_ONLY_FUNC_SPEC AFIO_HEADERS_ONLY_VIRTUAL_SPEC \
+EXPAND_AS_DEFINED = LLFIO_DECL LLFIO_DEADLINE_NAME LLFIO_MAKE_FREE_FUNCTION \
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC LLFIO_HEADERS_ONLY_FUNC_SPEC LLFIO_HEADERS_ONLY_VIRTUAL_SPEC \
QUICKCPPLIB_BITFIELD_BEGIN QUICKCPPLIB_BITFIELD_END \
- AFIO_V2_NAMESPACE AFIO_V2_NAMESPACE_BEGIN AFIO_V2_NAMESPACE_EXPORT_BEGIN AFIO_V2_NAMESPACE_END \
- AFIO_VERSION_GLUE2 AFIO_VERSION_GLUE AFIO_HEADERS_PATH4 AFIO_HEADERS_PATH3 AFIO_HEADERS_PATH2 \
- AFIO_HEADERS_PATH AFIO_MODULE_NAME \
- AFIO_VERSION_MAJOR AFIO_VERSION_MINOR \
- AFIO_REQUIRES
+ LLFIO_V2_NAMESPACE LLFIO_V2_NAMESPACE_BEGIN LLFIO_V2_NAMESPACE_EXPORT_BEGIN LLFIO_V2_NAMESPACE_END \
+ LLFIO_VERSION_GLUE2 LLFIO_VERSION_GLUE LLFIO_HEADERS_PATH4 LLFIO_HEADERS_PATH3 LLFIO_HEADERS_PATH2 \
+ LLFIO_HEADERS_PATH LLFIO_MODULE_NAME \
+ LLFIO_VERSION_MAJOR LLFIO_VERSION_MINOR \
+ LLFIO_REQUIRES
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
diff --git a/Readme.md b/Readme.md
index 258ed19b..29e27819 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,12 +1,12 @@
-This is the post-peer-review AFIO v2 rewrite. You can view its documentation at https://ned14.github.io/afio/
+This is the post-peer-review LLFIO v2 rewrite. You can view its documentation at https://ned14.github.io/llfio/
-<b>master branch test status</b> Linux & OS X: [![Build Status](https://travis-ci.org/ned14/afio.svg?branch=master)](https://travis-ci.org/ned14/afio) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/ox59o2r276xbmef7/branch/master?svg=true)](https://ci.appveyor.com/project/ned14/afio/branch/master) <b>CMake dashboard</b>: http://my.cdash.org/index.php?project=Boost.AFIO
+<b>master branch test status</b> Linux & OS X: [![Build Status](https://travis-ci.org/ned14/llfio.svg?branch=master)](https://travis-ci.org/ned14/llfio) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/dfctqfap3kpx89om/branch/master?svg=true)](https://ci.appveyor.com/project/ned14/llfio/branch/master) <b>CMake dashboard</b>: http://my.cdash.org/index.php?project=Boost.AFIO
Tarballs of source and prebuilt binaries for Linux x64, MacOS x64 and Windows x64:
-- https://dedi5.nedprod.com/static/files/afio-v2.0-source-latest.tar.xz
-- https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-linux64-latest.tgz
-- https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-darwin64-latest.tgz (disabled pending XCode supporting Filesystem TS)
-- https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-win64-latest.zip
+- https://dedi5.nedprod.com/static/files/llfio-v2.0-source-latest.tar.xz
+- https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-linux64-latest.tgz
+- https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-darwin64-latest.tgz (disabled pending XCode supporting Filesystem TS)
+- https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-win64-latest.zip
### Immediate todos in order of priority:
@@ -17,9 +17,10 @@ Tarballs of source and prebuilt binaries for Linux x64, MacOS x64 and Windows x6
- [x] Fix all known bugs in Outcome, plus reorg source code in prep for `status_code`.
- [x] Scatter-gather buffers to use https://github.com/martinmoene/byte-lite
- [x] Make lazy the stat fetch during file/dir open.
-- [x] Implement SG14 `status_code` as a standalone library and test in AFIO.
+- [x] Implement SG14 `status_code` as a standalone library and test in LLFIO.
- [x] Single include generation now we're on `status_code` and it's safe.
- [x] Implement `SIGBUS`/`EXCEPTION_IN_PAGE_ERROR` RAII catcher.
+- [ ] Implement `symlink_handle` already!
- [ ] `atomic_append` isn't actually being tested in shared_fs_mutex
- [ ] Implement a non-toy ACID key-value BLOB store and send it to Boost for peer review.
- [ ] For this need to implement a file-based B+ tree. And for that, need to
@@ -42,7 +43,7 @@ fuzzed, coverage calculated, bloat calculated, ABI dumped etc
### clang AST parser based todos which await me getting back into the clang AST parser:
-- [ ] C bindings for all AFIO v2 APIs. Write libclang parser which autogenerates
+- [ ] C bindings for all LLFIO v2 APIs. Write libclang parser which autogenerates
SWIG interface files from the .hpp files using custom attributes to fill in the
missing gaps.
- Much better coverage is to permute the *valid* parameter inputs of the kernel
@@ -107,7 +108,7 @@ the results directory where flags and OS get its own directory and each YAML fil
is named FS + device e.g.
-### Algorithms library `AFIO_V2_NAMESPACE::algorithm` todo:
+### Algorithms library `LLFIO_V2_NAMESPACE::algorithm` todo:
- [ ] Add `vector<T>` which adapts a `mapped_view<T>`.
- [ ] Add some primitive which intelligently copies/moves between views and vectors.
Specifically, if resizing, if type is trivially copyable, skip memory copying during
diff --git a/appveyor.yml b/appveyor.yml
index fad7da02..7c32fb43 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -13,7 +13,7 @@ image: Visual Studio 2017
init:
- git config --global core.longpaths true
-clone_folder: c:\boost.afio
+clone_folder: c:\boost.llfio
platform: x64
configuration: Release
environment:
@@ -32,9 +32,9 @@ test_script:
after_test:
on_success:
-# - set "NEWNAME=afio-v2.0-binaries-win64-%date:~10,4%%date:~4,2%%date:~7,2%%time:~0,2%%time:~3,2%.zip"
- - set "NEWNAME=afio-v2.0-binaries-win64-%APPVEYOR_REPO_COMMIT%.zip"
- - rename afio-v2.0-binaries-win64.zip %NEWNAME%
+# - set "NEWNAME=llfio-v2.0-binaries-win64-%date:~10,4%%date:~4,2%%date:~7,2%%time:~0,2%%time:~3,2%.zip"
+ - set "NEWNAME=llfio-v2.0-binaries-win64-%APPVEYOR_REPO_COMMIT%.zip"
+ - rename llfio-v2.0-binaries-win64.zip %NEWNAME%
- curl -T %NEWNAME% -u jenkins-nedprod:%JENKINS_NEDPROD_PASSWORD% https://dedi5.nedprod.com/static/files/upload/
on_failure:
on_finish:
diff --git a/cmake/headers.cmake b/cmake/headers.cmake
index 9199c39f..53a1dfd0 100644
--- a/cmake/headers.cmake
+++ b/cmake/headers.cmake
@@ -1,79 +1,83 @@
# DO NOT EDIT, GENERATED BY SCRIPT
-set(afio_HEADERS
- "include/afio/v2.0/deadline.h"
- "include/afio.hpp"
- "include/afio/afio.hpp"
- "include/afio/ntkernel-error-category/include/config.hpp"
- "include/afio/ntkernel-error-category/include/ntkernel_category.hpp"
- "include/afio/revision.hpp"
- "include/afio/v2.0/afio.hpp"
- "include/afio/v2.0/algorithm/cached_parent_handle_adapter.hpp"
- "include/afio/v2.0/algorithm/mapped_span.hpp"
- "include/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp"
- "include/afio/v2.0/algorithm/shared_fs_mutex/base.hpp"
- "include/afio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp"
- "include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp"
- "include/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp"
- "include/afio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp"
- "include/afio/v2.0/algorithm/trivial_vector.hpp"
- "include/afio/v2.0/async_file_handle.hpp"
- "include/afio/v2.0/config.hpp"
- "include/afio/v2.0/detail/impl/posix/import.hpp"
- "include/afio/v2.0/detail/impl/windows/import.hpp"
- "include/afio/v2.0/directory_handle.hpp"
- "include/afio/v2.0/file_handle.hpp"
- "include/afio/v2.0/fs_handle.hpp"
- "include/afio/v2.0/handle.hpp"
- "include/afio/v2.0/io_handle.hpp"
- "include/afio/v2.0/io_service.hpp"
- "include/afio/v2.0/logging.hpp"
- "include/afio/v2.0/map_handle.hpp"
- "include/afio/v2.0/mapped_file_handle.hpp"
- "include/afio/v2.0/native_handle_type.hpp"
- "include/afio/v2.0/path_discovery.hpp"
- "include/afio/v2.0/path_handle.hpp"
- "include/afio/v2.0/path_view.hpp"
- "include/afio/v2.0/stat.hpp"
- "include/afio/v2.0/statfs.hpp"
- "include/afio/v2.0/status_code.hpp"
- "include/afio/v2.0/storage_profile.hpp"
- "include/afio/v2.0/utils.hpp"
- "include/afio/version.hpp"
- "include/afio/ntkernel-error-category/include/detail/ntkernel-table.ipp"
- "include/afio/ntkernel-error-category/include/detail/ntkernel_category_impl.ipp"
- "include/afio/v2.0/detail/impl/cached_parent_handle_adapter.ipp"
- "include/afio/v2.0/detail/impl/path_discovery.ipp"
- "include/afio/v2.0/detail/impl/posix/async_file_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/directory_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/file_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/fs_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/handle.ipp"
- "include/afio/v2.0/detail/impl/posix/io_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/io_service.ipp"
- "include/afio/v2.0/detail/impl/posix/map_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/path_discovery.ipp"
- "include/afio/v2.0/detail/impl/posix/path_handle.ipp"
- "include/afio/v2.0/detail/impl/posix/stat.ipp"
- "include/afio/v2.0/detail/impl/posix/statfs.ipp"
- "include/afio/v2.0/detail/impl/posix/storage_profile.ipp"
- "include/afio/v2.0/detail/impl/posix/utils.ipp"
- "include/afio/v2.0/detail/impl/safe_byte_ranges.ipp"
- "include/afio/v2.0/detail/impl/storage_profile.ipp"
- "include/afio/v2.0/detail/impl/windows/async_file_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/directory_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/file_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/fs_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/handle.ipp"
- "include/afio/v2.0/detail/impl/windows/io_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/io_service.ipp"
- "include/afio/v2.0/detail/impl/windows/map_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/mapped_file_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/path_discovery.ipp"
- "include/afio/v2.0/detail/impl/windows/path_handle.ipp"
- "include/afio/v2.0/detail/impl/windows/path_view.ipp"
- "include/afio/v2.0/detail/impl/windows/stat.ipp"
- "include/afio/v2.0/detail/impl/windows/statfs.ipp"
- "include/afio/v2.0/detail/impl/windows/storage_profile.ipp"
- "include/afio/v2.0/detail/impl/windows/utils.ipp"
+set(llfio_HEADERS
+ "include/llfio/v2.0/deadline.h"
+ "include/llfio.hpp"
+ "include/llfio/llfio.hpp"
+ "include/llfio/ntkernel-error-category/include/config.hpp"
+ "include/llfio/ntkernel-error-category/include/ntkernel_category.hpp"
+ "include/llfio/revision.hpp"
+ "include/llfio/v2.0/algorithm/cached_parent_handle_adapter.hpp"
+ "include/llfio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp"
+ "include/llfio/v2.0/algorithm/shared_fs_mutex/base.hpp"
+ "include/llfio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp"
+ "include/llfio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp"
+ "include/llfio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp"
+ "include/llfio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp"
+ "include/llfio/v2.0/algorithm/trivial_vector.hpp"
+ "include/llfio/v2.0/async_file_handle.hpp"
+ "include/llfio/v2.0/config.hpp"
+ "include/llfio/v2.0/detail/impl/posix/import.hpp"
+ "include/llfio/v2.0/detail/impl/windows/import.hpp"
+ "include/llfio/v2.0/directory_handle.hpp"
+ "include/llfio/v2.0/file_handle.hpp"
+ "include/llfio/v2.0/fs_handle.hpp"
+ "include/llfio/v2.0/handle.hpp"
+ "include/llfio/v2.0/io_handle.hpp"
+ "include/llfio/v2.0/io_service.hpp"
+ "include/llfio/v2.0/llfio.hpp"
+ "include/llfio/v2.0/logging.hpp"
+ "include/llfio/v2.0/map_handle.hpp"
+ "include/llfio/v2.0/map_view.hpp"
+ "include/llfio/v2.0/mapped.hpp"
+ "include/llfio/v2.0/mapped_file_handle.hpp"
+ "include/llfio/v2.0/native_handle_type.hpp"
+ "include/llfio/v2.0/path_discovery.hpp"
+ "include/llfio/v2.0/path_handle.hpp"
+ "include/llfio/v2.0/path_view.hpp"
+ "include/llfio/v2.0/stat.hpp"
+ "include/llfio/v2.0/statfs.hpp"
+ "include/llfio/v2.0/status_code.hpp"
+ "include/llfio/v2.0/storage_profile.hpp"
+ "include/llfio/v2.0/symlink_handle.hpp"
+ "include/llfio/v2.0/utils.hpp"
+ "include/llfio/version.hpp"
+ "include/llfio/ntkernel-error-category/include/detail/ntkernel-table.ipp"
+ "include/llfio/ntkernel-error-category/include/detail/ntkernel_category_impl.ipp"
+ "include/llfio/v2.0/detail/impl/cached_parent_handle_adapter.ipp"
+ "include/llfio/v2.0/detail/impl/path_discovery.ipp"
+ "include/llfio/v2.0/detail/impl/posix/async_file_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/directory_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/file_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/fs_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/io_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/io_service.ipp"
+ "include/llfio/v2.0/detail/impl/posix/map_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/mapped_file_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/path_discovery.ipp"
+ "include/llfio/v2.0/detail/impl/posix/path_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/stat.ipp"
+ "include/llfio/v2.0/detail/impl/posix/statfs.ipp"
+ "include/llfio/v2.0/detail/impl/posix/storage_profile.ipp"
+ "include/llfio/v2.0/detail/impl/posix/symlink_handle.ipp"
+ "include/llfio/v2.0/detail/impl/posix/utils.ipp"
+ "include/llfio/v2.0/detail/impl/safe_byte_ranges.ipp"
+ "include/llfio/v2.0/detail/impl/storage_profile.ipp"
+ "include/llfio/v2.0/detail/impl/windows/async_file_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/directory_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/file_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/fs_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/io_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/io_service.ipp"
+ "include/llfio/v2.0/detail/impl/windows/map_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/mapped_file_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/path_discovery.ipp"
+ "include/llfio/v2.0/detail/impl/windows/path_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/path_view.ipp"
+ "include/llfio/v2.0/detail/impl/windows/stat.ipp"
+ "include/llfio/v2.0/detail/impl/windows/statfs.ipp"
+ "include/llfio/v2.0/detail/impl/windows/storage_profile.ipp"
+ "include/llfio/v2.0/detail/impl/windows/symlink_handle.ipp"
+ "include/llfio/v2.0/detail/impl/windows/utils.ipp"
)
diff --git a/cmake/interface.cmake b/cmake/interface.cmake
index f3c971d1..47a638c1 100644
--- a/cmake/interface.cmake
+++ b/cmake/interface.cmake
@@ -1,4 +1,4 @@
# DO NOT EDIT, GENERATED BY SCRIPT
-set(afio_INTERFACE
- "afio/afio.hpp"
+set(llfio_INTERFACE
+ "llfio/llfio.hpp"
)
diff --git a/cmake/sources.cmake b/cmake/sources.cmake
index 721109f9..db74ec95 100644
--- a/cmake/sources.cmake
+++ b/cmake/sources.cmake
@@ -1,4 +1,4 @@
# DO NOT EDIT, GENERATED BY SCRIPT
-set(afio_SOURCES
- "src/afio.cpp"
+set(llfio_SOURCES
+ "src/llfio.cpp"
)
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 895f5fd5..77a678c4 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -1,5 +1,5 @@
# DO NOT EDIT, GENERATED BY SCRIPT
-set(afio_TESTS
+set(llfio_TESTS
"test/test_kernel_decl.hpp"
"test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp"
"test/tests/directory_handle_enumerate/kernel_directory_handle_enumerate.cpp.hpp"
@@ -7,6 +7,7 @@ set(afio_TESTS
"test/tests/file_handle_create_close/kernel_file_handle.cpp.hpp"
"test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp"
"test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp"
+ "test/tests/symlink_handle_create_close/kernel_symlink_handle.cpp.hpp"
"test/tests/async_io.cpp"
"test/tests/coroutines.cpp"
"test/tests/current_path.cpp"
@@ -15,18 +16,20 @@ set(afio_TESTS
"test/tests/file_handle_create_close/runner.cpp"
"test/tests/file_handle_lock_unlock.cpp"
"test/tests/map_handle_create_close/runner.cpp"
- "test/tests/mapped_span.cpp"
+ "test/tests/mapped.cpp"
"test/tests/path_discovery.cpp"
"test/tests/path_view.cpp"
"test/tests/section_handle_create_close/runner.cpp"
"test/tests/shared_fs_mutex.cpp"
+ "test/tests/symlink_handle_create_close/runner.cpp"
"test/tests/trivial_vector.cpp"
)
# DO NOT EDIT, GENERATED BY SCRIPT
-set(afio_COMPILE_TESTS
+set(llfio_COMPILE_TESTS
"example/single-header.cpp"
+ "example/ts_examples.cpp"
"example/use_cases.cpp"
)
# DO NOT EDIT, GENERATED BY SCRIPT
-set(afio_COMPILE_FAIL_TESTS
+set(llfio_COMPILE_FAIL_TESTS
)
diff --git a/doc/html b/doc/html
-Subproject 925dba9720373bb34028cd5cb7667e618fe4d7d
+Subproject 5c9ae1aa255f1d41d65eeeb195ecc871c0f1b0b
diff --git a/doc/presentations/videos.txt b/doc/presentations/videos.txt
index d15d61ff..14f0f9b7 100644
--- a/doc/presentations/videos.txt
+++ b/doc/presentations/videos.txt
@@ -1,8 +1,8 @@
20150924 CppCon Racing the File System Workshop (good for the background on file systems)
https://www.youtube.com/watch?v=uhRWMGBjlO8
-20160421 ACCU Distributed Mutual Exclusion using Proposed AFIO (a bit of AFIO history and how and why it is designed, AFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::atomic_append)
+20160421 ACCU Distributed Mutual Exclusion using Proposed AFIO (a bit of LLFIO history and how and why it is designed, LLFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::atomic_append)
https://www.youtube.com/watch?v=elegewDwm64
-20160922 CppCon Better mutual exclusion on the filesystem using AFIO (pretty good overview of AFIO written to date, AFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::memory_map)
+20160922 CppCon Better mutual exclusion on the filesystem using AFIO (pretty good overview of LLFIO written to date, LLFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::memory_map)
https://www.youtube.com/watch?v=9l28ax3Zq0w
diff --git a/example/single-header.cpp b/example/single-header.cpp
index 4b0a4443..5160ed99 100644
--- a/example/single-header.cpp
+++ b/example/single-header.cpp
@@ -22,16 +22,16 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#if __has_include("../single-header/afio-win.hpp") && (_HAS_CXX17 || __cplusplus >= 201700)
+#if __has_include("../single-header/llfio-win.hpp") && (_HAS_CXX17 || __cplusplus >= 201700)
#ifdef _WIN32
-#include "../single-header/afio-win.hpp"
+#include "../single-header/llfio-win.hpp"
#else
-#include "../single-header/afio-posix.hpp"
+#include "../single-header/llfio-posix.hpp"
#endif
int main()
{
- AFIO_V2_NAMESPACE::mapped_file_handle v;
+ LLFIO_V2_NAMESPACE::mapped_file_handle v;
(void) v;
return 0;
}
diff --git a/example/ts_examples.cpp b/example/ts_examples.cpp
new file mode 100644
index 00000000..16c7c931
--- /dev/null
+++ b/example/ts_examples.cpp
@@ -0,0 +1,103 @@
+/* Examples from the P1031 Low level file i/o Technical Specification
+(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
+File Created: Aug 2018
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "../include/llfio.hpp"
+
+using namespace LLFIO_V2_NAMESPACE;
+using namespace std;
+
+#define throws(x)
+#define VALUE .value()
+
+inline io_handle::buffers_type read_all(io_handle &h, io_handle::io_request<io_handle::buffers_type> reqs, deadline d = deadline()) throws(file_io_error)
+{
+ // Record beginning if deadline is specified
+ chrono::steady_clock::time_point began_steady;
+ if(d && d.steady)
+ began_steady = chrono::steady_clock::now();
+
+ // Take copy of input buffers onto stack, and set output buffers to buffers supplied
+ auto *input_buffers_mem = reinterpret_cast<io_handle::buffer_type *>(alloca(reqs.buffers.size() * sizeof(io_handle::buffer_type)));
+ auto *input_buffers_sizes = reinterpret_cast<io_handle::extent_type *>(alloca(reqs.buffers.size() * sizeof(io_handle::extent_type)));
+ io_handle::buffers_type output_buffers(reqs.buffers);
+ io_handle::io_request<io_handle::buffers_type> creq({input_buffers_mem, reqs.buffers.size()}, 0);
+ for(size_t n = 0; n < reqs.buffers.size(); n++)
+ {
+ // Copy input buffer to stack and retain original size
+ creq.buffers[n] = reqs.buffers[n];
+ input_buffers_sizes[n] = reqs.buffers[n].size();
+ // Set output buffer length to zero
+ output_buffers[n] = io_handle::buffer_type{output_buffers[n].data(), 0};
+ }
+
+ // Track which output buffer we are currently filling
+ size_t idx = 0;
+ do
+ {
+ // New deadline for this loop
+ deadline nd;
+ if(d)
+ {
+ if(d.steady)
+ {
+ auto ns = chrono::duration_cast<chrono::nanoseconds>((began_steady + chrono::nanoseconds(d.nsecs)) - chrono::steady_clock::now());
+ if(ns.count() < 0)
+ nd.nsecs = 0;
+ else
+ nd.nsecs = ns.count();
+ }
+ else
+ nd = d;
+ }
+ // Partial fill buffers with current request
+ io_handle::buffers_type filled = h.read(creq, nd) VALUE;
+
+ // Adjust output buffers by what was filled, and prepare input
+ // buffers for next round of partial fill
+ for(size_t n = 0; n < creq.buffers.size(); n++)
+ {
+ // Add the amount of this buffer filled to next offset read and to output buffer
+ auto &input_buffer = creq.buffers[n];
+ auto &output_buffer = output_buffers[idx + n];
+ creq.offset += input_buffer.size();
+ output_buffer = io_handle::buffer_type{output_buffer.data(), output_buffer.size() + input_buffer.size()};
+ // Adjust input buffer to amount remaining
+ input_buffer = io_handle::buffer_type{input_buffer.data() + input_buffer.size(), input_buffers_sizes[idx + n] - output_buffer.size()};
+ }
+
+ // Remove completely filled input buffers
+ while(!creq.buffers.empty() && creq.buffers[0].size() == 0)
+ {
+ creq.buffers = io_handle::buffers_type(creq.buffers.data() + 1, creq.buffers.size() - 1);
+ ++idx;
+ }
+ } while(!creq.buffers.empty());
+ return output_buffers;
+}
+
+
+int main()
+{
+ return 0;
+} \ No newline at end of file
diff --git a/example/use_cases.cpp b/example/use_cases.cpp
index 65190ae3..740312d6 100644
--- a/example/use_cases.cpp
+++ b/example/use_cases.cpp
@@ -1,4 +1,4 @@
-/* Examples of AFIO use
+/* Examples of LLFIO use
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
File Created: Aug 2018
@@ -22,7 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../include/afio.hpp"
+#include "../include/llfio.hpp"
#include <future>
#include <iostream>
@@ -36,10 +36,10 @@ Distributed under the Boost Software License, Version 1.0.
void read_entire_file1()
{
//! [file_entire_file1]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Open the file for read
- afio::file_handle fh = afio::file( //
+ llfio::file_handle fh = llfio::file( //
{}, // path_handle to base directory
"foo" // path_view to path fragment relative to base directory
// default mode is read only
@@ -49,10 +49,10 @@ void read_entire_file1()
).value(); // If failed, throw a filesystem_error exception
// Make a vector sized the current maximum extent of the file
- std::vector<afio::byte> buffer(fh.maximum_extent().value());
+ std::vector<llfio::byte> buffer(fh.maximum_extent().value());
// Synchronous scatter read from file
- afio::file_handle::buffers_type filled = afio::read(
+ llfio::file_handle::buffers_type filled = llfio::read(
fh, // handle to read from
0, // offset
{{ buffer.data(), buffer.size() }} // Single scatter buffer of the vector
@@ -61,20 +61,20 @@ void read_entire_file1()
// In case of racy truncation of file by third party to new length, adjust buffer to
// bytes actually read
- buffer.resize(filled[0].len);
+ buffer.resize(filled[0].size());
//! [file_entire_file1]
}
void read_entire_file2()
{
//! [file_entire_file2]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Create an i/o service to complete the async file i/o
- afio::io_service service;
+ llfio::io_service service;
// Open the file for read
- afio::async_file_handle fh = afio::async_file( //
+ llfio::async_file_handle fh = llfio::async_file( //
service, // The i/o service to complete i/o to
{}, // path_handle to base directory
"foo" // path_view to path fragment relative to base directory
@@ -86,24 +86,24 @@ void read_entire_file2()
// Get the valid extents of the file.
const std::vector<
- std::pair<afio::file_handle::extent_type, afio::file_handle::extent_type>
+ std::pair<llfio::file_handle::extent_type, llfio::file_handle::extent_type>
> valid_extents = fh.extents().value();
// Schedule asynchronous reads for every valid extent
- std::vector<std::pair<std::vector<afio::byte>, afio::async_file_handle::io_state_ptr>> buffers(valid_extents.size());
+ std::vector<std::pair<std::vector<llfio::byte>, llfio::async_file_handle::io_state_ptr>> buffers(valid_extents.size());
for (size_t n = 0; n < valid_extents.size(); n++)
{
// Set up the scatter buffer
buffers[n].first.resize(valid_extents[n].second);
for(;;)
{
- afio::async_file_handle::buffer_type scatter_req{ buffers[n].first.data(), buffers[n].first.size() }; // buffer to fill
- auto ret = afio::async_read( //
+ llfio::async_file_handle::buffer_type scatter_req{ buffers[n].first.data(), buffers[n].first.size() }; // buffer to fill
+ auto ret = llfio::async_read( //
fh, // handle to read from
{ { scatter_req }, valid_extents[n].first }, // The scatter request buffers + offset
[]( // The completion handler
- afio::async_file_handle *, // The parent handle
- afio::async_file_handle::io_result<afio::async_file_handle::buffers_type> & // Result of the i/o
+ llfio::async_file_handle *, // The parent handle
+ llfio::async_file_handle::io_result<llfio::async_file_handle::buffers_type> & // Result of the i/o
) { /* do nothing */ }
// default deadline is infinite
);
@@ -114,7 +114,7 @@ void read_entire_file2()
buffers[n].second = std::move(ret).value();
break;
}
- if (ret.error() == afio::errc::resource_unavailable_try_again)
+ if (ret.error() == llfio::errc::resource_unavailable_try_again)
{
// Many async file i/o implementations have limited total system concurrency
std::this_thread::yield();
@@ -161,15 +161,15 @@ void scatter_write()
*/
return;
//! [scatter_write]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Open the file for write, creating if needed, don't cache reads nor writes
- afio::file_handle fh = afio::file( //
+ llfio::file_handle fh = llfio::file( //
{}, // path_handle to base directory
"hello", // path_view to path fragment relative to base directory
- afio::file_handle::mode::write, // write access please
- afio::file_handle::creation::if_needed, // create new file if needed
- afio::file_handle::caching::only_metadata // cache neither reads nor writes of data on this handle
+ llfio::file_handle::mode::write, // write access please
+ llfio::file_handle::creation::if_needed, // create new file if needed
+ llfio::file_handle::caching::only_metadata // cache neither reads nor writes of data on this handle
// default flags is none
).value(); // If failed, throw a filesystem_error exception
@@ -184,10 +184,10 @@ void scatter_write()
fh.write(0, // offset
{ // gather list, buffers use std::byte
- { reinterpret_cast<const afio::byte *>(a), sizeof(a) - 1 },
- { reinterpret_cast<const afio::byte *>(b), sizeof(b) - 1 },
- { reinterpret_cast<const afio::byte *>(c), sizeof(c) - 1 },
- { reinterpret_cast<const afio::byte *>(d), sizeof(d) - 1 },
+ { reinterpret_cast<const llfio::byte *>(a), sizeof(a) - 1 },
+ { reinterpret_cast<const llfio::byte *>(b), sizeof(b) - 1 },
+ { reinterpret_cast<const llfio::byte *>(c), sizeof(c) - 1 },
+ { reinterpret_cast<const llfio::byte *>(d), sizeof(d) - 1 },
}
// default deadline is infinite
).value(); // If failed, throw a filesystem_error exception
@@ -200,18 +200,18 @@ void scatter_write()
void malloc1()
{
//! [malloc1]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Call whatever the equivalent to mmap() is on this platform to fetch
// new private memory backed by the swap file. This will be the system
// all bits zero page mapped into each page of the allocation. Only on
// first write will a page fault allocate a real zeroed page for that
// page.
- afio::map_handle mh = afio::map(4096).value();
+ llfio::map_handle mh = llfio::map(4096).value();
// Fill the newly allocated memory with 'a' C style. For each first write
// to a page, it will be page faulted into a private page by the kernel.
- afio::byte *p = mh.address();
+ llfio::byte *p = mh.address();
size_t len = mh.length();
memset(p, 'a', len);
@@ -224,7 +224,7 @@ void malloc1()
mh.do_not_store({mh.address(), mh.length()}).value();
// Fill the memory with 'b' C++ style, probably faulting new pages into existence
- afio::algorithm::mapped_span<char> p2(mh);
+ llfio::map_view<char> p2(mh);
std::fill(p2.begin(), p2.end(), 'b');
// Kick the contents of the memory out to the swap file so it is no longer cached in RAM
@@ -238,14 +238,14 @@ void malloc1()
// And rather than wait until first page fault read, tell the system we are going to
// use this region soon. Most systems will begin an asynchronous population of the
// kernel page cache immediately.
- afio::map_handle::buffer_type pf[] = { { mh.address(), mh.length() } };
+ llfio::map_handle::buffer_type pf[] = { { mh.address(), mh.length() } };
mh.prefetch(pf).value();
// You can actually save yourself some time and skip manually creating map handles.
// Just construct a mapped_span directly, this creates an internal map_handle instance,
// so memory is released when the span is destroyed
- afio::algorithm::mapped_span<float> f(1000); // 1000 floats, allocated used mmap()
+ llfio::mapped<float> f(1000); // 1000 floats, allocated used mmap()
std::fill(f.begin(), f.end(), 1.23f);
//! [malloc1]
}
@@ -253,28 +253,28 @@ void malloc1()
void malloc2()
{
//! [malloc2]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Create 4Kb of anonymous shared memory. This will persist
// until the last handle to it in the system is destructed.
// You can fetch a path to it to give to other processes using
// sh.current_path()
- afio::section_handle sh = afio::section(4096).value();
+ llfio::section_handle sh = llfio::section(4096).value();
{
// Map it into memory, and fill it with 'a'
- afio::algorithm::mapped_span<char> ms1(sh);
+ llfio::mapped<char> ms1(sh);
std::fill(ms1.begin(), ms1.end(), 'a');
// Destructor unmaps it from memory
}
// Map it into memory again, verify it contains 'a'
- afio::algorithm::mapped_span<char> ms1(sh);
+ llfio::mapped<char> ms1(sh);
assert(ms1[0] == 'a');
// Map a *second view* of the same memory
- afio::algorithm::mapped_span<char> ms2(sh);
+ llfio::mapped<char> ms2(sh);
assert(ms2[0] == 'a');
// The addresses of the two maps are unique
@@ -289,10 +289,10 @@ void malloc2()
void map_file()
{
//! [map_file]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Open the file for read
- afio::file_handle rfh = afio::file( //
+ llfio::file_handle rfh = llfio::file( //
{}, // path_handle to base directory
"foo" // path_view to path fragment relative to base directory
// default mode is read only
@@ -302,25 +302,25 @@ void map_file()
).value(); // If failed, throw a filesystem_error exception
// Open the same file for atomic append
- afio::file_handle afh = afio::file( //
+ llfio::file_handle afh = llfio::file( //
{}, // path_handle to base directory
"foo", // path_view to path fragment relative to base directory
- afio::file_handle::mode::append // open for atomic append
+ llfio::file_handle::mode::append // open for atomic append
// default creation is open existing
// default caching is all
// default flags is none
).value(); // If failed, throw a filesystem_error exception
// Create a section for the file of exactly the current length of the file
- afio::section_handle sh = afio::section(rfh).value();
+ llfio::section_handle sh = llfio::section(rfh).value();
// Map the end of the file into memory with a 1Mb address reservation
- afio::map_handle mh = afio::map(sh, 1024 * 1024, sh.length().value() & ~4095).value();
+ llfio::map_handle mh = llfio::map(sh, 1024 * 1024, sh.length().value() & ~4095).value();
// Append stuff to append only handle
- afio::write(afh,
+ llfio::write(afh,
0, // offset is ignored for atomic append only handles
- {{ reinterpret_cast<const afio::byte *>("hello"), 6 }} // single gather buffer
+ {{ reinterpret_cast<const llfio::byte *>("hello"), 6 }} // single gather buffer
// default deadline is infinite
).value();
@@ -342,10 +342,10 @@ void map_file()
void mapped_file()
{
//! [mapped_file]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Open the mapped file for read
- afio::mapped_file_handle mh = afio::mapped_file( //
+ llfio::mapped_file_handle mh = llfio::mapped_file( //
{}, // path_handle to base directory
"foo" // path_view to path fragment relative to base directory
// default mode is read only
@@ -370,17 +370,17 @@ void mapped_file()
void sparse_array()
{
//! [sparse_array]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Make me a 1 trillion element sparsely allocated integer array!
- afio::mapped_file_handle mfh = afio::mapped_temp_inode().value();
+ llfio::mapped_file_handle mfh = llfio::mapped_temp_inode().value();
// On an extents based filing system, doesn't actually allocate any physical
// storage but does map approximately 4Tb of all bits zero data into memory
(void) mfh.truncate(1000000000000ULL * sizeof(int));
// Create a typed view of the one trillion integers
- afio::algorithm::mapped_span<int> one_trillion_int_array(mfh);
+ llfio::map_view<int> one_trillion_int_array(mfh);
// Write and read as you see fit, if you exceed physical RAM it'll be paged out
one_trillion_int_array[0] = 5;
@@ -392,14 +392,14 @@ void sparse_array()
std::future<void> coroutine_write()
{
//! [coroutine_write]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Create an asynchronous file handle
- afio::io_service service;
- afio::async_file_handle fh =
- afio::async_file(service, {}, "testfile.txt",
- afio::async_file_handle::mode::write,
- afio::async_file_handle::creation::if_needed).value();
+ llfio::io_service service;
+ llfio::async_file_handle fh =
+ llfio::async_file(service, {}, "testfile.txt",
+ llfio::async_file_handle::mode::write,
+ llfio::async_file_handle::creation::if_needed).value();
// Resize it to 1024 bytes
truncate(fh, 1024).value();
@@ -408,7 +408,7 @@ std::future<void> coroutine_write()
// suspending execution of this coroutine until completion and then resuming
// execution. Requires the Coroutines TS.
alignas(4096) char buffer[] = "hello world";
- co_await co_write(fh, 0, { { reinterpret_cast<afio::byte *>(buffer), sizeof(buffer) } }).value();
+ co_await co_write(fh, 0, { { reinterpret_cast<llfio::byte *>(buffer), sizeof(buffer) } }).value();
//! [coroutine_write]
}
#endif
diff --git a/include/afio.hpp b/include/afio.hpp
deleted file mode 100644
index a74367f3..00000000
--- a/include/afio.hpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "afio/afio.hpp"
diff --git a/include/afio/afio.hpp b/include/afio/afio.hpp
deleted file mode 100644
index 6e6163d6..00000000
--- a/include/afio/afio.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//! \file afio/afio.hpp The master *latest version* AFIO include file. All AFIO consuming libraries should include this header only.
-#include "version.hpp"
-
-#if defined(_MSC_VER) && !defined(__clang__)
-#define AFIO_HEADERS_PATH2 AFIO_VERSION_GLUE(v, AFIO_HEADERS_VERSION, /afio.hpp)
-#elif !__PCPP_ALWAYS_FALSE__
-#define AFIO_HEADERS_PATH2 AFIO_VERSION_GLUE(v, AFIO_HEADERS_VERSION,)/afio.hpp
-#endif
-
-#if 0 // cmake's Makefiles and Ninja generators won't pick up dependent headers without this
-#include "v2.0/afio.hpp"
-#endif
-
-#define AFIO_HEADERS_PATH4(a) #a
-#define AFIO_HEADERS_PATH3(a) AFIO_HEADERS_PATH4(a)
-//! \brief The AFIO headers path generated by the preprocessor from the version
-#define AFIO_HEADERS_PATH AFIO_HEADERS_PATH3(AFIO_HEADERS_PATH2)
-#include AFIO_HEADERS_PATH
-#undef AFIO_HEADERS_PATH
-#undef AFIO_HEADERS_PATH2
-#undef AFIO_HEADERS_PATH3
-#undef AFIO_HEADERS_PATH4
diff --git a/include/afio/afio.ixx b/include/afio/afio.ixx
deleted file mode 100644
index f6197437..00000000
--- a/include/afio/afio.ixx
+++ /dev/null
@@ -1,4 +0,0 @@
-// Tell the headers we are generating the interface for the library
-#define GENERATING_AFIO_MODULE_INTERFACE
-module afio_v2_0; // AFIO_MODULE_NAME
-#include "afio.hpp"
diff --git a/include/afio/ntkernel-error-category b/include/afio/ntkernel-error-category
deleted file mode 160000
-Subproject 8b1bc49c852feaadf99b815e63dffb8b6a7cd0c
diff --git a/include/afio/revision.hpp b/include/afio/revision.hpp
deleted file mode 100644
index 0814ade3..00000000
--- a/include/afio/revision.hpp
+++ /dev/null
@@ -1,4 +0,0 @@
-// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define AFIO_PREVIOUS_COMMIT_REF bd06afea35d760e6de395b047a9524c55bf44588
-#define AFIO_PREVIOUS_COMMIT_DATE "2018-06-29 22:05:49 +00:00"
-#define AFIO_PREVIOUS_COMMIT_UNIQUE bd06afea
diff --git a/include/afio/v2.0/afio.hpp b/include/afio/v2.0/afio.hpp
deleted file mode 100644
index be31688c..00000000
--- a/include/afio/v2.0/afio.hpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//! \file v2.0/afio.hpp The master *versioned* AFIO include file. All version specific AFIO consuming libraries should include this header only.
-
-#undef AFIO_VERSION_MAJOR
-#undef AFIO_VERSION_MINOR
-#undef AFIO_VERSION_PATCH
-// Remove any previously defined versioning
-#undef AFIO_VERSION_REVISION
-#undef AFIO_VERSION_GLUE2
-#undef AFIO_VERSION_GLUE
-#undef AFIO_HEADERS_VERSION
-#undef AFIO_NAMESPACE_VERSION
-#undef AFIO_MODULE_NAME
-
-#define AFIO_VERSION_GLUE2(a, b, c) a##b##c
-#define AFIO_VERSION_GLUE(a, b, c) AFIO_VERSION_GLUE2(a, b, c)
-
-// Hard coded as this is a specific version
-#define AFIO_VERSION_MAJOR 2
-#define AFIO_VERSION_MINOR 0
-#define AFIO_VERSION_PATCH 0
-#define AFIO_VERSION_REVISION 0
-//! \brief The namespace AFIO_V2_NAMESPACE::v ## AFIO_NAMESPACE_VERSION
-#define AFIO_NAMESPACE_VERSION AFIO_VERSION_GLUE(AFIO_VERSION_MAJOR, _, AFIO_VERSION_MINOR)
-
-#if defined(__cpp_modules) || defined(DOXYGEN_SHOULD_SKIP_THIS)
-#if defined(_MSC_VER) && !defined(__clang__)
-//! \brief The AFIO C++ module name
-#define AFIO_MODULE_NAME AFIO_VERSION_GLUE(afio_v, AFIO_NAMESPACE_VERSION, )
-#else
-//! \brief The AFIO C++ module name
-#define AFIO_MODULE_NAME AFIO_VERSION_GLUE(afio_v, AFIO_NAMESPACE_VERSION, )
-#endif
-#endif
-
-// If C++ Modules are on and we are not compiling the library,
-// we are either generating the interface or importing
-#if defined(__cpp_modules)
-#if defined(GENERATING_AFIO_MODULE_INTERFACE)
-// We are generating this module's interface
-#define QUICKCPPLIB_HEADERS_ONLY 0
-#define AFIO_HEADERS_ONLY 0
-#define AFIO_INCLUDE_ALL
-#elif defined(AFIO_SOURCE)
-// We are implementing this module
-#define AFIO_INCLUDE_ALL
-#else
-// We are importing this module
-import AFIO_MODULE_NAME;
-#undef AFIO_INCLUDE_ALL
-#endif
-#else
-// C++ Modules not on, therefore include as usual
-#define AFIO_INCLUDE_ALL
-#endif
-
-#ifdef AFIO_INCLUDE_ALL
-
-#include "config.hpp"
-
-// Predeclare to keep the single header edition happy
-#include "handle.hpp"
-#include "stat.hpp"
-#include "utils.hpp"
-
-#ifndef AFIO_LEAN_AND_MEAN
-#include "async_file_handle.hpp"
-#else
-#include "file_handle.hpp"
-#endif
-#include "directory_handle.hpp"
-#include "map_handle.hpp"
-#include "statfs.hpp"
-#ifndef AFIO_LEAN_AND_MEAN
-#include "storage_profile.hpp"
-#endif
-
-#include "algorithm/cached_parent_handle_adapter.hpp"
-#include "algorithm/mapped_span.hpp"
-#include "algorithm/shared_fs_mutex/atomic_append.hpp"
-#include "algorithm/shared_fs_mutex/byte_ranges.hpp"
-#include "algorithm/shared_fs_mutex/lock_files.hpp"
-#include "algorithm/shared_fs_mutex/memory_map.hpp"
-#include "algorithm/shared_fs_mutex/safe_byte_ranges.hpp"
-#include "algorithm/trivial_vector.hpp"
-
-#endif
diff --git a/include/afio/v2.0/algorithm/mapped_span.hpp b/include/afio/v2.0/algorithm/mapped_span.hpp
deleted file mode 100644
index 1ab2c292..00000000
--- a/include/afio/v2.0/algorithm/mapped_span.hpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/* A typed view of a mapped section
-(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
-File Created: Aug 2017
-
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License in the accompanying file
-Licence.txt or at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-
-Distributed under the Boost Software License, Version 1.0.
- (See accompanying file Licence.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-*/
-
-#ifndef AFIO_MAPPED_VIEW_HPP
-#define AFIO_MAPPED_VIEW_HPP
-
-#include "../mapped_file_handle.hpp"
-#include "../utils.hpp"
-
-//! \file mapped_span.hpp Provides typed view of mapped section.
-
-AFIO_V2_NAMESPACE_BEGIN
-
-namespace algorithm
-{
- /*! \brief Provides a typed mapped view of a `section_handle` suitable for feeding to STL algorithms
- or the Ranges TS by wrapping a `map_handle` into a `span<T>`.
-
- Optionally can issue a blocking write barrier on destruction of the mapped view by setting the flag
- `section_handle::flag::barrier_on_close`, thus forcing any changes to data referred to by the view
- to storage before the destructor returns.
- */
- template <class T> class mapped_span : public span<T>
- {
- public:
- //! The extent type.
- using extent_type = typename section_handle::extent_type;
- //! The size type.
- using size_type = typename section_handle::size_type;
-
- private:
- map_handle _mapping;
- mapped_span(extent_type page_offset, extent_type offset, section_handle &sh, size_type bytes, section_handle::flag _flag) // NOLINT
- : _mapping(map_handle::map(sh, (bytes == 0) ? 0 : bytes + (offset - page_offset), page_offset, _flag).value())
- {
- offset -= page_offset;
- byte *addr = _mapping.address() + offset;
- size_t len = sh.length().value() - offset; // use section length, not mapped length as mapped length is rounded up to page size
- if(bytes != 0 && bytes < len)
- {
- len = bytes;
- }
- static_cast<span<T> &>(*this) = span<T>(reinterpret_cast<T *>(addr), len / sizeof(T)); // NOLINT
- }
-
- public:
- //! Default constructor
- constexpr mapped_span() {} // NOLINT
-
- /*! Create a view of new memory.
-
- \param length The number of items to map.
- \param _flag The flags to pass to `map_handle::map()`.
- */
- explicit mapped_span(size_type length, section_handle::flag _flag = section_handle::flag::readwrite)
- : _mapping(map_handle::map(length * sizeof(T), _flag).value())
- {
- byte *addr = _mapping.address();
- static_cast<span<T> &>(*this) = span<T>(reinterpret_cast<T *>(addr), length); // NOLINT
- }
- /*! Construct a mapped view of the given section handle.
-
- \param sh The section handle to use as the data source for creating the map.
- \param length The number of items to map, use -1 to mean the length of the section handle divided by `sizeof(T)`.
- \param byteoffset The byte offset into the section handle, this does not need to be a multiple of the page size.
- \param _flag The flags to pass to `map_handle::map()`.
- */
- explicit mapped_span(section_handle &sh, size_type length = (size_type) -1, extent_type byteoffset = 0, section_handle::flag _flag = section_handle::flag::readwrite) // NOLINT
- : mapped_span((length == 0) ? mapped_span() : mapped_span(
-#ifdef _WIN32
- byteoffset & ~65535,
-#else
- utils::round_down_to_page_size(byteoffset),
-#endif
- byteoffset, sh, (length == (size_type) -1) ? 0 : length * sizeof(T), _flag)) // NOLINT
- {
- }
- /*! Construct a mapped view of the given map handle.
-
- \param mh The map handle to use.
- \param length The number of items to map, use -1 to mean the length of the map handle divided by `sizeof(T)`.
- \param byteoffset The byte offset into the map handle, this does not need to be a multiple of the page size.
- */
- explicit mapped_span(map_handle &mh, size_type length = (size_type) -1, extent_type byteoffset = 0) // NOLINT
- : span<T>(reinterpret_cast<T *>(mh.address() + byteoffset), (length == (size_type) -1) ? ((mh.length() - byteoffset) / sizeof(T)) : length) // NOLINT
- {
- }
- /*! Construct a mapped view of the given mapped file handle.
-
- \param mfh The mapped file handle to use as the data source for creating the map.
- \param length The number of items to map, use -1 to mean the length of the section handle divided by `sizeof(T)`.
- \param byteoffset The byte offset into the mapped file handle, this does not need to be a multiple of the page size.
- */
- explicit mapped_span(mapped_file_handle &mfh, size_type length = (size_type) -1, extent_type byteoffset = 0) // NOLINT
- : span<T>(reinterpret_cast<T *>(mfh.address() + byteoffset), (length == (size_type) -1) ? ((mfh.maximum_extent().value() - byteoffset) / sizeof(T)) : length) // NOLINT
- {
- }
- };
-} // namespace algorithm
-
-AFIO_V2_NAMESPACE_END
-
-#endif
diff --git a/include/afio/v2.0/deadline.h b/include/afio/v2.0/deadline.h
deleted file mode 100644
index e4629843..00000000
--- a/include/afio/v2.0/deadline.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Specifies a time deadline
-(C) 2015-2017 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
-File Created: Dec 2015
-
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License in the accompanying file
-Licence.txt or at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-
-Distributed under the Boost Software License, Version 1.0.
- (See accompanying file Licence.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-*/
-
-#ifndef AFIO_DEADLINE_H
-#define AFIO_DEADLINE_H
-
-#include <stdbool.h> // NOLINT
-#include <time.h> // NOLINT
-
-//! \file deadline.h Provides struct deadline
-
-#if defined(__cplusplus) || DOXYGEN_IS_IN_THE_HOUSE
-#ifndef AFIO_CONFIG_HPP
-#error You must include the master afio.hpp, not individual header files directly
-#endif
-#include "config.hpp"
-#include <stdexcept>
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
-#define AFIO_DEADLINE_NAME deadline
-#else
-#define AFIO_DEADLINE_NAME boost_afio_deadline
-#endif
-
-/*! \struct deadline
-\brief A time deadline in either relative-to-now or absolute (system clock) terms
-*/
-struct AFIO_DEADLINE_NAME
-{
- //! True if deadline does not change with system clock changes
- bool steady; // NOLINT
- union {
- //! System time from timespec_get(&ts, TIME_UTC)
- struct timespec utc; // NOLINT
- //! Nanosecond ticks from start of operation
- unsigned long long nsecs; // NOLINT
- };
-#ifdef __cplusplus
- constexpr deadline() // NOLINT
- : steady(false),
- utc{0, 0}
- {
- }
- //! True if deadline is valid
- constexpr explicit operator bool() const noexcept { return steady || utc.tv_sec != 0; }
- //! Implicitly construct a deadline from a system clock time point
- deadline(std::chrono::system_clock::time_point tp) // NOLINT
- : steady(false),
- utc{0, 0}
- {
- std::chrono::seconds secs(std::chrono::system_clock::to_time_t(tp));
- utc.tv_sec = secs.count();
- std::chrono::system_clock::time_point _tp(std::chrono::system_clock::from_time_t(utc.tv_sec));
- utc.tv_nsec = static_cast<long>(std::chrono::duration_cast<std::chrono::nanoseconds>(tp - _tp).count());
- }
- //! Implicitly construct a deadline from a duration from now
- template <class Rep, class Period>
- constexpr deadline(std::chrono::duration<Rep, Period> d) // NOLINT
- : steady(true),
- nsecs(0)
- {
- std::chrono::nanoseconds _nsecs = std::chrono::duration_cast<std::chrono::nanoseconds>(d);
- // Negative durations are zero duration
- if(_nsecs.count() > 0)
- {
- nsecs = _nsecs.count();
- }
- else
- {
- nsecs = 0;
- }
- }
- //! Returns a system_clock::time_point for this deadline
- std::chrono::system_clock::time_point to_time_point() const
- {
- if(steady)
- {
- throw std::invalid_argument("Not a UTC deadline!"); // NOLINT
- }
- std::chrono::system_clock::time_point tp(std::chrono::system_clock::from_time_t(utc.tv_sec));
- tp += std::chrono::duration_cast<std::chrono::system_clock::duration>(std::chrono::nanoseconds(utc.tv_nsec));
- return tp;
- }
-#endif
-};
-
-#undef AFIO_DEADLINE_NAME
-#if defined(__cplusplus) || DOXYGEN_IS_IN_THE_HOUSE
-AFIO_V2_NAMESPACE_END
-#endif
-
-#endif
diff --git a/include/afio/v2.0/outcome b/include/afio/v2.0/outcome
deleted file mode 160000
-Subproject 2f521b22a9417cd75108c73aa62822a17538fa9
diff --git a/include/afio/v2.0/quickcpplib b/include/afio/v2.0/quickcpplib
deleted file mode 160000
-Subproject a820b995ea46514ecec9394324a9bb397853252
diff --git a/include/afio/version.hpp b/include/afio/version.hpp
deleted file mode 100644
index 7f337cf3..00000000
--- a/include/afio/version.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//! \file version.hpp Controls the version of AFIO for cmake, shared library and C++ namespace mangling
-#undef AFIO_VERSION_MAJOR
-#undef AFIO_VERSION_MINOR
-#undef AFIO_VERSION_PATCH
-#undef AFIO_VERSION_REVISION
-#undef AFIO_VERSION_GLUE2
-#undef AFIO_VERSION_GLUE
-#undef AFIO_HEADERS_VERSION
-#undef AFIO_NAMESPACE_VERSION
-
-//! \brief Major version for cmake and DLL version stamping \ingroup config
-#define AFIO_VERSION_MAJOR 2
-//! \brief Minor version for cmake and DLL version stamping \ingroup config
-#define AFIO_VERSION_MINOR 0
-//! \brief Patch version for cmake and DLL version stamping \ingroup config
-#define AFIO_VERSION_PATCH 0
-//! \brief Revision version for cmake and DLL version stamping \ingroup config
-#define AFIO_VERSION_REVISION 0
-
-//! \brief Defined between stable releases of AFIO. It means the inline namespace
-//! will be permuted per-commit to ensure ABI uniqueness. \ingroup config
-#define AFIO_UNSTABLE_VERSION
-
-#define AFIO_VERSION_GLUE2(a, b, c) a ## b ## c
-#define AFIO_VERSION_GLUE(a, b, c) AFIO_VERSION_GLUE2(a, b, c)
-#define AFIO_NAMESPACE_VERSION AFIO_VERSION_GLUE(AFIO_VERSION_MAJOR, _, AFIO_VERSION_MINOR)
-
-#if defined(_MSC_VER) && !defined(__clang__)
-#define AFIO_HEADERS_VERSION AFIO_VERSION_GLUE(AFIO_VERSION_MAJOR, ., AFIO_VERSION_MINOR)
-#else
-#define AFIO_HEADERS_VERSION AFIO_VERSION_MAJOR.AFIO_VERSION_MINOR
-#endif
-//! \brief The namespace AFIO_V2_NAMESPACE::v ## AFIO_NAMESPACE_VERSION
-#define AFIO_NAMESPACE_VERSION AFIO_VERSION_GLUE(AFIO_VERSION_MAJOR, _, AFIO_VERSION_MINOR)
diff --git a/include/llfio.hpp b/include/llfio.hpp
new file mode 100644
index 00000000..eb93f8ff
--- /dev/null
+++ b/include/llfio.hpp
@@ -0,0 +1 @@
+#include "llfio/llfio.hpp"
diff --git a/include/llfio/llfio.hpp b/include/llfio/llfio.hpp
new file mode 100644
index 00000000..180df4ae
--- /dev/null
+++ b/include/llfio/llfio.hpp
@@ -0,0 +1,22 @@
+//! \file llfio/llfio.hpp The master *latest version* LLFIO include file. All LLFIO consuming libraries should include this header only.
+#include "version.hpp"
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#define LLFIO_HEADERS_PATH2 LLFIO_VERSION_GLUE(v, LLFIO_HEADERS_VERSION, /llfio.hpp)
+#elif !__PCPP_ALWAYS_FALSE__
+#define LLFIO_HEADERS_PATH2 LLFIO_VERSION_GLUE(v, LLFIO_HEADERS_VERSION,)/llfio.hpp
+#endif
+
+#if 0 // cmake's Makefiles and Ninja generators won't pick up dependent headers without this
+#include "v2.0/llfio.hpp"
+#endif
+
+#define LLFIO_HEADERS_PATH4(a) #a
+#define LLFIO_HEADERS_PATH3(a) LLFIO_HEADERS_PATH4(a)
+//! \brief The LLFIO headers path generated by the preprocessor from the version
+#define LLFIO_HEADERS_PATH LLFIO_HEADERS_PATH3(LLFIO_HEADERS_PATH2)
+#include LLFIO_HEADERS_PATH
+#undef LLFIO_HEADERS_PATH
+#undef LLFIO_HEADERS_PATH2
+#undef LLFIO_HEADERS_PATH3
+#undef LLFIO_HEADERS_PATH4
diff --git a/include/llfio/llfio.ixx b/include/llfio/llfio.ixx
new file mode 100644
index 00000000..d0ce163d
--- /dev/null
+++ b/include/llfio/llfio.ixx
@@ -0,0 +1,4 @@
+// Tell the headers we are generating the interface for the library
+#define GENERATING_LLFIO_MODULE_INTERFACE
+module llfio_v2_0; // LLFIO_MODULE_NAME
+#include "llfio.hpp"
diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp
new file mode 100644
index 00000000..28c2279f
--- /dev/null
+++ b/include/llfio/revision.hpp
@@ -0,0 +1,4 @@
+// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
+#define LLFIO_PREVIOUS_COMMIT_REF 83b7ad9bfda9af36414d8d6acac454288cb90a3a
+#define LLFIO_PREVIOUS_COMMIT_DATE "2018-08-14 19:05:09 +00:00"
+#define LLFIO_PREVIOUS_COMMIT_UNIQUE 83b7ad9b
diff --git a/include/afio/v2.0/algorithm/cached_parent_handle_adapter.hpp b/include/llfio/v2.0/algorithm/cached_parent_handle_adapter.hpp
index ad5a7eb7..308d8451 100644
--- a/include/afio/v2.0/algorithm/cached_parent_handle_adapter.hpp
+++ b/include/llfio/v2.0/algorithm/cached_parent_handle_adapter.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_CACHED_PARENT_HANDLE_ADAPTER_HPP
-#define AFIO_CACHED_PARENT_HANDLE_ADAPTER_HPP
+#ifndef LLFIO_CACHED_PARENT_HANDLE_ADAPTER_HPP
+#define LLFIO_CACHED_PARENT_HANDLE_ADAPTER_HPP
#include "../directory_handle.hpp"
@@ -33,13 +33,13 @@ Distributed under the Boost Software License, Version 1.0.
#endif
//! \file cached_parent_handle_adapter.hpp Adapts any `fs_handle` to cache its parent directory handle
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
namespace detail
{
- struct AFIO_DECL cached_path_handle : public std::enable_shared_from_this<cached_path_handle>
+ struct LLFIO_DECL cached_path_handle : public std::enable_shared_from_this<cached_path_handle>
{
directory_handle h;
filesystem::path _lastpath;
@@ -47,11 +47,11 @@ namespace algorithm
: h(std::move(_h))
{
}
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<filesystem::path> current_path(const filesystem::path &append) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<filesystem::path> current_path(const filesystem::path &append) noexcept;
};
using cached_path_handle_ptr = std::shared_ptr<cached_path_handle>;
// Passed the base and path of the adapted handle being created, returns a handle to the containing directory and the leafname
- AFIO_HEADERS_ONLY_FUNC_SPEC std::pair<cached_path_handle_ptr, filesystem::path> get_cached_path_handle(const path_handle &base, path_view path);
+ LLFIO_HEADERS_ONLY_FUNC_SPEC std::pair<cached_path_handle_ptr, filesystem::path> get_cached_path_handle(const path_handle &base, path_view path);
} // namespace detail
/*! \brief Adapts any `construct()`-able implementation to cache its parent directory handle in a process wide cache.
@@ -72,7 +72,7 @@ namespace algorithm
result in the inability to do race free unlinking etc, but if no third party changes are encountered it ought
to work well.
*/
- template <class T> AFIO_REQUIRES(sizeof(construct<T>) > 0) class AFIO_DECL cached_parent_handle_adapter : public T
+ template <class T> LLFIO_REQUIRES(sizeof(construct<T>) > 0) class LLFIO_DECL cached_parent_handle_adapter : public T
{
static_assert(sizeof(construct<T>) > 0, "Type T must be registered with the construct<T> framework so cached_parent_handle_adapter<T> knows how to construct it"); // NOLINT
@@ -91,7 +91,12 @@ namespace algorithm
cached_parent_handle_adapter(const cached_parent_handle_adapter &) = default;
cached_parent_handle_adapter(cached_parent_handle_adapter &&) = default; // NOLINT
cached_parent_handle_adapter &operator=(const cached_parent_handle_adapter &) = default;
- cached_parent_handle_adapter &operator=(cached_parent_handle_adapter &&) = default; // NOLINT
+ cached_parent_handle_adapter &operator=(cached_parent_handle_adapter &&o) noexcept
+ {
+ this->~cached_parent_handle_adapter();
+ new(this) cached_parent_handle_adapter(std::move(o));
+ return *this;
+ }
cached_parent_handle_adapter(adapted_handle_type &&o, const path_handle &base, path_view path)
: adapted_handle_type(std::move(o))
{
@@ -99,43 +104,43 @@ namespace algorithm
_sph = std::move(r.first);
_leafname = std::move(r.second);
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~cached_parent_handle_adapter() override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~cached_parent_handle_adapter() override
{
if(this->_v)
{
(void) cached_parent_handle_adapter::close();
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_type> current_path() const noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_type> current_path() const noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
return (_sph != nullptr) ? _sph->current_path(_leafname) : path_type();
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
OUTCOME_TRYV(adapted_handle_type::close());
_sph.reset();
_leafname.clear();
return success();
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
_sph.reset();
_leafname.clear();
return adapted_handle_type::release();
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_handle> parent_path_handle(deadline /* unused */ = std::chrono::seconds(30)) const noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_handle> parent_path_handle(deadline /* unused */ = std::chrono::seconds(30)) const noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
OUTCOME_TRY(ret, _sph->h.clone_to_path_handle());
return {std::move(ret)};
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
result<void> relink(const path_handle &base, path_view_type newpath, bool atomic_replace = true, deadline d = std::chrono::seconds(30)) noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
OUTCOME_TRYV(adapted_handle_type::relink(base, newpath, atomic_replace, d));
_sph.reset();
_leafname.clear();
@@ -151,10 +156,10 @@ namespace algorithm
return error_from_exception();
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
result<void> unlink(deadline d = std::chrono::seconds(30)) noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
OUTCOME_TRYV(adapted_handle_type::unlink(d));
_sph.reset();
_leafname.clear();
@@ -200,12 +205,12 @@ template <class T> struct construct<algorithm::cached_parent_handle_adapter<T>>
}
};
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#include "../detail/impl/cached_parent_handle_adapter.ipp"
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp b/include/llfio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
index 5bcec29b..39d08564 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
+++ b/include/llfio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_SHARED_FS_MUTEX_ATOMIC_APPEND_HPP
-#define AFIO_SHARED_FS_MUTEX_ATOMIC_APPEND_HPP
+#ifndef LLFIO_SHARED_FS_MUTEX_ATOMIC_APPEND_HPP
+#define LLFIO_SHARED_FS_MUTEX_ATOMIC_APPEND_HPP
#include "../../file_handle.hpp"
#include "base.hpp"
@@ -33,7 +33,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file atomic_append.hpp Provides algorithm::shared_fs_mutex::atomic_append
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -105,7 +105,7 @@ namespace algorithm
- If your OS doesn't have sane byte range locks (OS X, BSD, older Linuxes) and multiple
objects in your process use the same lock file, misoperation will occur. Use lock_files instead.
- \todo Implement hole punching once I port that code from AFIO v1.
+ \todo Implement hole punching once I port that code from LLFIO v1.
\todo Decide on some resolution mechanism for sudden process exit.
\todo There is a 1 out of 2^64-2 chance of unique id collision. It would be nice if we
actually formally checked that our chosen unique id is actually unique.
@@ -139,9 +139,9 @@ namespace algorithm
do
{
OUTCOME_TRY(_, _h.read(0, {{reinterpret_cast<byte *>(&_header), 48}}));
- if(_[0].data != reinterpret_cast<byte *>(&_header))
+ if(_[0].data() != reinterpret_cast<byte *>(&_header))
{
- memcpy(&_header, _[0].data, _[0].len);
+ memcpy(&_header, _[0].data(), _[0].size());
}
if(_skip_hashing)
{
@@ -191,10 +191,10 @@ namespace algorithm
ZFS, btrfs) guarantee atomicity of updates and therefore torn writes are never
observed by readers. For these, hashing can be safely disabled.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<atomic_append> fs_mutex_append(const path_handle &base, path_view lockfile, bool nfs_compatibility = false, bool skip_hashing = false) noexcept
{
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
OUTCOME_TRY(ret, file_handle::file(base, lockfile, file_handle::mode::write, file_handle::creation::if_needed, file_handle::caching::temporary));
atomic_append_detail::header header;
// Lock the entire header for exclusive access
@@ -237,9 +237,9 @@ namespace algorithm
const file_handle &handle() const noexcept { return _h; }
protected:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
atomic_append_detail::lock_request lock_request;
if(out.entities.size() > sizeof(lock_request.entities) / sizeof(lock_request.entities[0]))
{
@@ -303,11 +303,12 @@ namespace algorithm
// Should never happen :)
if(readoutcome.has_error())
{
- AFIO_LOG_FATAL(this, "atomic_append::lock() saw an error when searching for just written data");
+ LLFIO_LOG_FATAL(this, "atomic_append::lock() saw an error when searching for just written data");
std::terminate();
}
const atomic_append_detail::lock_request *record, *lastrecord;
- for(record = reinterpret_cast<const atomic_append_detail::lock_request *>(readoutcome.value()[0].data), lastrecord = reinterpret_cast<const atomic_append_detail::lock_request *>(readoutcome.value()[0].data + readoutcome.value()[0].len); record < lastrecord && record->hash != lock_request.hash; ++record)
+ for(record = reinterpret_cast<const atomic_append_detail::lock_request *>(readoutcome.value()[0].data()), lastrecord = reinterpret_cast<const atomic_append_detail::lock_request *>(readoutcome.value()[0].data() + readoutcome.value()[0].size()); record < lastrecord && record->hash != lock_request.hash;
+ ++record)
{
my_lock_request_offset += sizeof(atomic_append_detail::lock_request);
}
@@ -361,9 +362,9 @@ namespace algorithm
assert(record_offset >= start_offset);
assert(record_offset - start_offset <= sizeof(_buffer));
OUTCOME_TRY(batchread, _h.read(start_offset, {{_buffer, (size_t)(record_offset - start_offset) + sizeof(atomic_append_detail::lock_request)}}));
- assert(batchread[0].len == record_offset - start_offset + sizeof(atomic_append_detail::lock_request));
- const atomic_append_detail::lock_request *record = reinterpret_cast<atomic_append_detail::lock_request *>(batchread[0].data + batchread[0].len - sizeof(atomic_append_detail::lock_request));
- const atomic_append_detail::lock_request *firstrecord = reinterpret_cast<atomic_append_detail::lock_request *>(batchread[0].data);
+ assert(batchread[0].size() == record_offset - start_offset + sizeof(atomic_append_detail::lock_request));
+ const atomic_append_detail::lock_request *record = reinterpret_cast<atomic_append_detail::lock_request *>(batchread[0].data() + batchread[0].size() - sizeof(atomic_append_detail::lock_request));
+ const atomic_append_detail::lock_request *firstrecord = reinterpret_cast<atomic_append_detail::lock_request *>(batchread[0].data());
// Skip all completed lock requests or not mentioning any of my entities
for(; record >= firstrecord; record_offset -= sizeof(atomic_append_detail::lock_request), --record)
@@ -460,13 +461,13 @@ namespace algorithm
}
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long hint) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long hint) noexcept final
{
(void) entities;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(hint == 0u)
{
- AFIO_LOG_WARN(this, "atomic_append::unlock() currently requires a hint to work, assuming this is a failed lock.");
+ LLFIO_LOG_WARN(this, "atomic_append::unlock() currently requires a hint to work, assuming this is a failed lock.");
return;
}
auto my_lock_request_offset = static_cast<file_handle::extent_type>(hint);
@@ -476,13 +477,13 @@ namespace algorithm
(void) _h.read(my_lock_request_offset, {{(byte *) &record, sizeof(record)}});
if(!record.unique_id)
{
- AFIO_LOG_FATAL(this, "atomic_append::unlock() I have been previously unlocked!");
+ LLFIO_LOG_FATAL(this, "atomic_append::unlock() I have been previously unlocked!");
std::terminate();
}
(void) _read_header();
if(_header.first_known_good > my_lock_request_offset)
{
- AFIO_LOG_FATAL(this, "atomic_append::unlock() header exceeds the lock I am unlocking!");
+ LLFIO_LOG_FATAL(this, "atomic_append::unlock() header exceeds the lock I am unlocking!");
std::terminate();
}
#endif
@@ -510,12 +511,12 @@ namespace algorithm
}
const auto &bytesread = bytesread_.value();
// If read was partial, we are done after this round
- if(bytesread[0].len < sizeof(_buffer))
+ if(bytesread[0].size() < sizeof(_buffer))
{
done = true;
}
- const auto *record = reinterpret_cast<const atomic_append_detail::lock_request *>(bytesread[0].data);
- const auto *lastrecord = reinterpret_cast<const atomic_append_detail::lock_request *>(bytesread[0].data + bytesread[0].len);
+ const auto *record = reinterpret_cast<const atomic_append_detail::lock_request *>(bytesread[0].data());
+ const auto *lastrecord = reinterpret_cast<const atomic_append_detail::lock_request *>(bytesread[0].data() + bytesread[0].size());
for(; record < lastrecord; ++record)
{
if(!record->hash && (record->unique_id == 0u))
@@ -551,7 +552,7 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/base.hpp b/include/llfio/v2.0/algorithm/shared_fs_mutex/base.hpp
index e0c111ef..9e958054 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/base.hpp
+++ b/include/llfio/v2.0/algorithm/shared_fs_mutex/base.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_SHARED_FS_MUTEX_BASE_HPP
-#define AFIO_SHARED_FS_MUTEX_BASE_HPP
+#ifndef LLFIO_SHARED_FS_MUTEX_BASE_HPP
+#define LLFIO_SHARED_FS_MUTEX_BASE_HPP
#include "../../handle.hpp"
@@ -42,7 +42,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file base.hpp Provides algorithm::shared_fs_mutex::shared_fs_mutex
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -113,7 +113,7 @@ namespace algorithm
shared_fs_mutex &operator=(shared_fs_mutex &&) = default;
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~shared_fs_mutex() = default;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~shared_fs_mutex() = default;
//! Generates an entity id from a sequence of bytes
entity_type entity_from_buffer(const char *buffer, size_t bytes, bool exclusive = true) noexcept
@@ -238,7 +238,7 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp b/include/llfio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp
index 1fe9fb13..dfc99e9c 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp
+++ b/include/llfio/v2.0/algorithm/shared_fs_mutex/byte_ranges.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_SHARED_FS_MUTEX_BYTE_RANGES_HPP
-#define AFIO_SHARED_FS_MUTEX_BYTE_RANGES_HPP
+#ifndef LLFIO_SHARED_FS_MUTEX_BYTE_RANGES_HPP
+#define LLFIO_SHARED_FS_MUTEX_BYTE_RANGES_HPP
#include "../../file_handle.hpp"
#include "base.hpp"
@@ -42,7 +42,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file byte_ranges.hpp Provides algorithm::shared_fs_mutex::byte_ranges
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -110,10 +110,10 @@ namespace algorithm
}
//! Initialises a shared filing system mutex using the file at \em lockfile
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<byte_ranges> fs_mutex_byte_ranges(const path_handle &base, path_view lockfile) noexcept
{
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
OUTCOME_TRY(ret, file_handle::file(base, lockfile, file_handle::mode::write, file_handle::creation::if_needed, file_handle::caching::temporary));
return byte_ranges(std::move(ret));
}
@@ -122,9 +122,9 @@ namespace algorithm
const file_handle &handle() const noexcept { return _h; }
protected:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
std::chrono::steady_clock::time_point began_steady;
std::chrono::system_clock::time_point end_utc;
if(d)
@@ -234,9 +234,9 @@ namespace algorithm
}
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long /*hint*/) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long /*hint*/) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
for(const auto &i : entities)
{
_h.unlock(i.value, 1);
@@ -247,7 +247,7 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp b/include/llfio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
index 33b3b31d..ff33520b 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
+++ b/include/llfio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_SHARED_FS_MUTEX_LOCK_FILES_HPP
-#define AFIO_SHARED_FS_MUTEX_LOCK_FILES_HPP
+#ifndef LLFIO_SHARED_FS_MUTEX_LOCK_FILES_HPP
+#define LLFIO_SHARED_FS_MUTEX_LOCK_FILES_HPP
#include "../../file_handle.hpp"
#include "base.hpp"
@@ -43,7 +43,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file lock_files.hpp Provides algorithm::shared_fs_mutex::lock_files
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -113,10 +113,10 @@ namespace algorithm
}
//! Initialises a shared filing system mutex using the directory at \em lockdir which MUST stay valid for the duration of this lock.
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<lock_files> fs_mutex_lock_files(const path_handle &lockdir) noexcept
{
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
return lock_files(lockdir);
}
@@ -124,9 +124,9 @@ namespace algorithm
const path_handle &path() const noexcept { return _path; }
protected:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
std::chrono::steady_clock::time_point began_steady;
std::chrono::system_clock::time_point end_utc;
if(d)
@@ -222,9 +222,9 @@ namespace algorithm
}
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type /*entities*/, unsigned long long /*hint*/) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type /*entities*/, unsigned long long /*hint*/) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
for(auto &i : _hs)
{
(void) i.close(); // delete on close semantics deletes the file
@@ -235,7 +235,7 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp b/include/llfio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
index b71de0b2..724e0773 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
+++ b/include/llfio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_SHARED_FS_MUTEX_MEMORY_MAP_HPP
-#define AFIO_SHARED_FS_MUTEX_MEMORY_MAP_HPP
+#ifndef LLFIO_SHARED_FS_MUTEX_MEMORY_MAP_HPP
+#define LLFIO_SHARED_FS_MUTEX_MEMORY_MAP_HPP
#include "../../map_handle.hpp"
#include "base.hpp"
@@ -51,7 +51,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file memory_map.hpp Provides algorithm::shared_fs_mutex::memory_map
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -63,7 +63,7 @@ namespace algorithm
\tparam HashIndexSize The size in bytes of the hash index to use (defaults to 4Kb)
\tparam SpinlockType The type of spinlock to use (defaults to a `SharedMutex` concept spinlock)
- This is the highest performing filing system mutex in AFIO, but it comes with a long list of potential
+ This is the highest performing filing system mutex in LLFIO, but it comes with a long list of potential
gotchas. It works by creating a random temporary file somewhere on the system and placing its path
in a file at the lock file location. The random temporary file is mapped into memory by all processes
using the lock where an open addressed hash table is kept. Each entity is hashed into somewhere in the
@@ -168,7 +168,7 @@ namespace algorithm
#ifndef NDEBUG
if(!lockresult && lockresult.error() != errc::timed_out)
{
- AFIO_LOG_FATAL(0, "memory_map::~memory_map() try_lock failed");
+ LLFIO_LOG_FATAL(0, "memory_map::~memory_map() try_lock failed");
abort();
}
#endif
@@ -178,7 +178,7 @@ namespace algorithm
auto o2 = _h.truncate(0);
if(!o2)
{
- AFIO_LOG_FATAL(0, "memory_map::~memory_map() truncate failed");
+ LLFIO_LOG_FATAL(0, "memory_map::~memory_map() truncate failed");
#ifndef NDEBUG
std::cerr << "~memory_map() truncate failed due to " << o2.error().message().c_str() << std::endl;
#endif
@@ -193,7 +193,7 @@ namespace algorithm
std::cerr << "~memory_map() unlink failed due to " << o3.error().message().c_str() << std::endl;
#endif
#else
- AFIO_LOG_FATAL(0, "memory_map::~memory_map() unlink failed");
+ LLFIO_LOG_FATAL(0, "memory_map::~memory_map() unlink failed");
#ifndef NDEBUG
std::cerr << "~memory_map() unlink failed due to " << o3.error().message().c_str() << std::endl;
#endif
@@ -209,10 +209,10 @@ namespace algorithm
but a particularly important one is `errc::no_lock_available` which will be returned if the lock
is in use by another computer on a network.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<memory_map> fs_mutex_map(const path_handle &base, path_view lockfile) noexcept
{
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
try
{
OUTCOME_TRY(ret, file_handle::file(base, lockfile, file_handle::mode::write, file_handle::creation::if_needed, file_handle::caching::reads));
@@ -323,9 +323,9 @@ namespace algorithm
}
return span<_entity_idx>(entity_to_idx, ep - entity_to_idx);
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
std::chrono::steady_clock::time_point began_steady;
std::chrono::system_clock::time_point end_utc;
if(d)
@@ -407,9 +407,9 @@ namespace algorithm
}
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long /*unused*/) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long /*unused*/) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
span<_entity_idx> entity_to_idx(_hash_entities(reinterpret_cast<_entity_idx *>(alloca(sizeof(_entity_idx) * entities.size())), entities));
_hash_index_type &index = _index();
for(const auto &i : entity_to_idx)
@@ -422,7 +422,7 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp b/include/llfio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp
index b388dd70..313607dd 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp
+++ b/include/llfio/v2.0/algorithm/shared_fs_mutex/safe_byte_ranges.hpp
@@ -22,12 +22,12 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_SHARED_FS_MUTEX_SAFE_BYTE_RANGES_HPP
-#define AFIO_SHARED_FS_MUTEX_SAFE_BYTE_RANGES_HPP
+#ifndef LLFIO_SHARED_FS_MUTEX_SAFE_BYTE_RANGES_HPP
+#define LLFIO_SHARED_FS_MUTEX_SAFE_BYTE_RANGES_HPP
#if defined(_WIN32)
#include "byte_ranges.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -42,7 +42,7 @@ namespace algorithm
{
}
//! Initialises a shared filing system mutex using the file at \em lockfile
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<safe_byte_ranges> fs_mutex_safe_byte_ranges(const path_handle &base, path_view lockfile) noexcept
{
OUTCOME_TRY(v, byte_ranges::fs_mutex_byte_ranges(base, lockfile));
@@ -52,7 +52,7 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#else
@@ -62,7 +62,7 @@ AFIO_V2_NAMESPACE_END
//! \file safe_byte_ranges.hpp Provides algorithm::shared_fs_mutex::safe_byte_ranges
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -70,7 +70,7 @@ namespace algorithm
{
namespace detail
{
- AFIO_HEADERS_ONLY_FUNC_SPEC result<std::shared_ptr<shared_fs_mutex>> inode_to_fs_mutex(const path_handle &base, path_view lockfile) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<std::shared_ptr<shared_fs_mutex>> inode_to_fs_mutex(const path_handle &base, path_view lockfile) noexcept;
}
/*! \class safe_byte_ranges
@@ -149,7 +149,7 @@ namespace algorithm
}
//! Initialises a shared filing system mutex using the file at \em lockfile
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<safe_byte_ranges> fs_mutex_safe_byte_ranges(const path_handle &base, path_view lockfile) noexcept
{
OUTCOME_TRY(ret, detail::inode_to_fs_mutex(base, lockfile));
@@ -157,21 +157,21 @@ namespace algorithm
}
protected:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final { return _p->_lock(out, d, spin_not_sleep); }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final { return _p->_lock(out, d, spin_not_sleep); }
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long hint) noexcept final { return _p->unlock(entities, hint); }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long hint) noexcept final { return _p->unlock(entities, hint); }
};
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#include "../../detail/impl/safe_byte_ranges.ipp"
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#endif
diff --git a/include/afio/v2.0/algorithm/trivial_vector.hpp b/include/llfio/v2.0/algorithm/trivial_vector.hpp
index 0089092b..f94de9ac 100644
--- a/include/afio/v2.0/algorithm/trivial_vector.hpp
+++ b/include/llfio/v2.0/algorithm/trivial_vector.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_ALGORITHM_VECTOR_HPP
-#define AFIO_ALGORITHM_VECTOR_HPP
+#ifndef LLFIO_ALGORITHM_VECTOR_HPP
+#define LLFIO_ALGORITHM_VECTOR_HPP
#include "../map_handle.hpp"
#include "../utils.hpp"
@@ -31,7 +31,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file trivial_vector.hpp Provides constant time reallocating STL vector.
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -679,7 +679,7 @@ L3 4Mb:
536870912,405524,294685
*/
#ifndef DOXYGEN_IS_IN_THE_HOUSE
- template <class T> AFIO_REQUIRES(std::is_trivially_copyable<T>::value) class trivial_vector : public detail::trivial_vector_impl<std::is_default_constructible<T>::value, T>
+ template <class T> LLFIO_REQUIRES(std::is_trivially_copyable<T>::value) class trivial_vector : public detail::trivial_vector_impl<std::is_default_constructible<T>::value, T>
#else
template <class T> class trivial_vector : public impl::trivial_vector_impl<true, T>
#endif
@@ -708,6 +708,6 @@ L3 4Mb:
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/async_file_handle.hpp b/include/llfio/v2.0/async_file_handle.hpp
index 8eed1c2b..bdca7b1e 100644
--- a/include/afio/v2.0/async_file_handle.hpp
+++ b/include/llfio/v2.0/async_file_handle.hpp
@@ -27,10 +27,10 @@ Distributed under the Boost Software License, Version 1.0.
//! \file async_file_handle.hpp Provides async_file_handle
-#ifndef AFIO_ASYNC_FILE_HANDLE_H
-#define AFIO_ASYNC_FILE_HANDLE_H
+#ifndef LLFIO_ASYNC_FILE_HANDLE_H
+#define LLFIO_ASYNC_FILE_HANDLE_H
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
@@ -60,7 +60,7 @@ runs the i/o service's `run()` function.
\snippet coroutines.cpp coroutines_example
*/
-class AFIO_DECL async_file_handle : public file_handle
+class LLFIO_DECL async_file_handle : public file_handle
{
friend class io_service;
@@ -114,7 +114,7 @@ public:
//! No copy assignment
async_file_handle &operator=(const async_file_handle &) = delete;
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(async_file_handle &o) noexcept
{
async_file_handle temp(std::move(*this));
@@ -134,8 +134,8 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<async_file_handle> async_file(io_service &service, const path_handle &base, path_view_type _path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::only_metadata, flag flags = flag::none) noexcept
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<async_file_handle> async_file(io_service &service, const path_handle &base, path_view_type _path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::only_metadata, flag flags = flag::none) noexcept
{
// Open it overlapped, otherwise no difference.
OUTCOME_TRY(v, file_handle::file(std::move(base), _path, _mode, _creation, _caching, flags | flag::overlapped));
@@ -150,7 +150,7 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<async_file_handle> async_random_file(io_service &service, const path_handle &dirpath, mode _mode = mode::write, caching _caching = caching::only_metadata, flag flags = flag::none) noexcept
{
try
@@ -186,7 +186,7 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<async_file_handle> async_temp_file(io_service &service, path_view_type name = path_view_type(), mode _mode = mode::write, creation _creation = creation::if_needed, caching _caching = caching::only_metadata, flag flags = flag::unlink_on_first_close) noexcept
{
auto &tempdirh = path_discovery::storage_backed_temporary_files_directory();
@@ -202,8 +202,8 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<async_file_handle> async_temp_inode(io_service &service, const path_handle &dir = path_discovery::storage_backed_temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<async_file_handle> async_temp_inode(io_service &service, const path_handle &dir = path_discovery::storage_backed_temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept
{
// Open it overlapped, otherwise no difference.
OUTCOME_TRY(v, file_handle::temp_inode(dir, _mode, flags | flag::overlapped));
@@ -212,8 +212,8 @@ public:
return std::move(ret);
}
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
/*! Clone this handle to a different io_service (copy constructor is disabled to avoid accidental copying)
\errors Any of the values POSIX dup() or DuplicateHandle() can return.
@@ -225,7 +225,7 @@ public:
ret._service = &service;
return std::move(ret);
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept override
{
OUTCOME_TRY(v, file_handle::clone(mode_, caching_, d));
async_file_handle ret(std::move(v));
@@ -274,13 +274,13 @@ protected:
, items_to_go(0)
{
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~_erased_io_state_type()
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~_erased_io_state_type()
{
// i/o still pending is very bad, this should never happen
assert(!items_to_go);
if(items_to_go != 0u)
{
- AFIO_LOG_FATAL(parent->native_handle().h, "FATAL: io_state destructed while i/o still in flight, the derived class should never allow this.");
+ LLFIO_LOG_FATAL(parent->native_handle().h, "FATAL: io_state destructed while i/o still in flight, the derived class should never allow this.");
abort();
}
}
@@ -352,8 +352,8 @@ protected:
_erased_completion_handler &operator=(_erased_completion_handler &&) = default;
_erased_completion_handler &operator=(const _erased_completion_handler &) = default;
};
- template <class BuffersType, class IORoutine> result<io_state_ptr> AFIO_HEADERS_ONLY_MEMFUNC_SPEC _begin_io(span<char> mem, operation_t operation, io_request<BuffersType> reqs, _erased_completion_handler &&completion, IORoutine &&ioroutine) noexcept;
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<io_state_ptr> _begin_io(span<char> mem, operation_t operation, io_request<const_buffers_type> reqs, _erased_completion_handler &&completion) noexcept;
+ template <class BuffersType, class IORoutine> result<io_state_ptr> LLFIO_HEADERS_ONLY_MEMFUNC_SPEC _begin_io(span<char> mem, operation_t operation, io_request<BuffersType> reqs, _erased_completion_handler &&completion, IORoutine &&ioroutine) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<io_state_ptr> _begin_io(span<char> mem, operation_t operation, io_request<const_buffers_type> reqs, _erased_completion_handler &&completion) noexcept;
public:
/*! \brief Schedule a barrier to occur asynchronously.
@@ -375,12 +375,12 @@ public:
\mallocs If mem is not set, one calloc, one free. The allocation is unavoidable due to the need to store a type
erased completion handler of unknown type and state per buffers input.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
template <class CompletionRoutine> //
- AFIO_REQUIRES(detail::is_invocable_r<void, CompletionRoutine, async_file_handle *, io_result<const_buffers_type> &>::value) //
+ LLFIO_REQUIRES(detail::is_invocable_r<void, CompletionRoutine, async_file_handle *, io_result<const_buffers_type> &>::value) //
result<io_state_ptr> async_barrier(io_request<const_buffers_type> reqs, CompletionRoutine &&completion, bool wait_for_device = false, bool and_metadata = false, span<char> mem = {}) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
struct completion_handler : _erased_completion_handler
{
CompletionRoutine completion;
@@ -430,12 +430,12 @@ public:
\mallocs If mem is not set, one calloc, one free. The allocation is unavoidable due to the need to store a type
erased completion handler of unknown type and state per buffers input.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
template <class CompletionRoutine> //
- AFIO_REQUIRES(detail::is_invocable_r<void, CompletionRoutine, async_file_handle *, io_result<buffers_type> &>::value) //
+ LLFIO_REQUIRES(detail::is_invocable_r<void, CompletionRoutine, async_file_handle *, io_result<buffers_type> &>::value) //
result<io_state_ptr> async_read(io_request<buffers_type> reqs, CompletionRoutine &&completion, span<char> mem = {}) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
struct completion_handler : _erased_completion_handler
{
CompletionRoutine completion;
@@ -473,12 +473,12 @@ public:
\mallocs If mem in not set, one calloc, one free. The allocation is unavoidable due to the need to store a type
erased completion handler of unknown type and state per buffers input.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
template <class CompletionRoutine> //
- AFIO_REQUIRES(detail::is_invocable_r<void, CompletionRoutine, async_file_handle *, io_result<const_buffers_type> &>::value) //
+ LLFIO_REQUIRES(detail::is_invocable_r<void, CompletionRoutine, async_file_handle *, io_result<const_buffers_type> &>::value) //
result<io_state_ptr> async_write(io_request<const_buffers_type> reqs, CompletionRoutine &&completion, span<char> mem = {}) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
struct completion_handler : _erased_completion_handler
{
CompletionRoutine completion;
@@ -499,9 +499,9 @@ public:
}
using file_handle::read;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override;
using file_handle::write;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override;
#if defined(__cpp_coroutines) || defined(DOXYGEN_IS_IN_THE_HOUSE)
private:
@@ -558,14 +558,14 @@ public:
\errors As for read(), plus ENOMEM.
\mallocs One calloc, one free.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
result<awaitable<buffers_type>> co_read(io_request<buffers_type> reqs) noexcept
{
OUTCOME_TRY(r, async_read(reqs, awaitable_state<buffers_type>()));
return awaitable<buffers_type>(std::move(r));
}
//! \overload
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
result<awaitable<buffers_type>> co_read(extent_type offset, std::initializer_list<buffer_type> lst) noexcept
{
buffer_type *_reqs = reinterpret_cast<buffer_type *>(alloca(sizeof(buffer_type) * lst.size()));
@@ -584,14 +584,14 @@ public:
\errors As for write(), plus ENOMEM.
\mallocs One calloc, one free.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
result<awaitable<const_buffers_type>> co_write(io_request<const_buffers_type> reqs) noexcept
{
OUTCOME_TRY(r, async_write(reqs, awaitable_state<const_buffers_type>()));
return awaitable<const_buffers_type>(std::move(r));
}
//! \overload
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
result<awaitable<const_buffers_type>> co_write(extent_type offset, std::initializer_list<const_buffer_type> lst) noexcept
{
const_buffer_type *_reqs = reinterpret_cast<const_buffer_type *>(alloca(sizeof(const_buffer_type) * lst.size()));
@@ -803,16 +803,16 @@ inline result<async_file_handle::awaitable<async_file_handle::const_buffers_type
#endif
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/async_file_handle.ipp"
#else
#include "detail/impl/posix/async_file_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#endif
diff --git a/include/afio/v2.0/config.hpp b/include/llfio/v2.0/config.hpp
index c6f08c9d..e08db987 100644
--- a/include/afio/v2.0/config.hpp
+++ b/include/llfio/v2.0/config.hpp
@@ -1,4 +1,4 @@
-/* Configures AFIO
+/* Configures LLFIO
(C) 2015-2018 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: Dec 2015
@@ -22,86 +22,86 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_CONFIG_HPP
-#define AFIO_CONFIG_HPP
+#ifndef LLFIO_CONFIG_HPP
+#define LLFIO_CONFIG_HPP
//#include <iostream>
-//#define AFIO_LOG_TO_OSTREAM std::cerr
-//#define AFIO_LOGGING_LEVEL 6
-//#define AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+//#define LLFIO_LOG_TO_OSTREAM std::cerr
+//#define LLFIO_LOGGING_LEVEL 1
+//#define LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
-//! \file config.hpp Configures a compiler environment for AFIO header and source code
+//! \file config.hpp Configures a compiler environment for LLFIO header and source code
//! \defgroup config Configuration macros
-#if !defined(AFIO_HEADERS_ONLY) && !defined(BOOST_ALL_DYN_LINK)
-//! \brief Whether AFIO is a headers only library. Defaults to 1 unless BOOST_ALL_DYN_LINK is defined. \ingroup config
-#define AFIO_HEADERS_ONLY 1
+#if !defined(LLFIO_HEADERS_ONLY) && !defined(BOOST_ALL_DYN_LINK)
+//! \brief Whether LLFIO is a headers only library. Defaults to 1 unless BOOST_ALL_DYN_LINK is defined. \ingroup config
+#define LLFIO_HEADERS_ONLY 1
#endif
-//! \def AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+//! \def LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
//! \brief Define to not record the current handle's path in any failure info.
#if DOXYGEN_IS_IN_THE_HOUSE
-#define AFIO_DISABLE_PATHS_IN_FAILURE_INFO not defined
+#define LLFIO_DISABLE_PATHS_IN_FAILURE_INFO not defined
#endif
-#if !defined(AFIO_LOGGING_LEVEL)
+#if !defined(LLFIO_LOGGING_LEVEL)
//! \brief How much detail to log. 0=disabled, 1=fatal, 2=error, 3=warn, 4=info, 5=debug, 6=all.
//! Defaults to error level. \ingroup config
#ifdef NDEBUG
-#define AFIO_LOGGING_LEVEL 1 // fatal
+#define LLFIO_LOGGING_LEVEL 1 // fatal
#else
-#define AFIO_LOGGING_LEVEL 3 // warn
+#define LLFIO_LOGGING_LEVEL 3 // warn
#endif
#endif
-#ifndef AFIO_LOG_TO_OSTREAM
-#if !defined(NDEBUG) && !defined(AFIO_DISABLE_LOG_TO_OSTREAM)
+#ifndef LLFIO_LOG_TO_OSTREAM
+#if !defined(NDEBUG) && !defined(LLFIO_DISABLE_LOG_TO_OSTREAM)
#include <iostream> // for std::cerr
//! \brief Any `ostream` to also log to. If `NDEBUG` is not defined, `std::cerr` is the default.
-#define AFIO_LOG_TO_OSTREAM std::cerr
+#define LLFIO_LOG_TO_OSTREAM std::cerr
#endif
#endif
-#if !defined(AFIO_LOG_BACKTRACE_LEVELS)
+#if !defined(LLFIO_LOG_BACKTRACE_LEVELS)
//! \brief Bit mask of which log levels should be stack backtraced
//! which will slow those logs thirty fold or so. Defaults to (1U<<1U)|(1U<<2U)|(1U<<3U) i.e. stack backtrace
//! on fatal, error and warn logs. \ingroup config
-#define AFIO_LOG_BACKTRACE_LEVELS ((1U << 1U) | (1U << 2U) | (1U << 3U))
+#define LLFIO_LOG_BACKTRACE_LEVELS ((1U << 1U) | (1U << 2U) | (1U << 3U))
#endif
-#if !defined(AFIO_LOGGING_MEMORY)
+#if !defined(LLFIO_LOGGING_MEMORY)
#ifdef NDEBUG
-#define AFIO_LOGGING_MEMORY 4096
+#define LLFIO_LOGGING_MEMORY 4096
#else
//! \brief How much memory to use for the log.
//! Defaults to 4Kb if NDEBUG defined, else 1Mb. \ingroup config
-#define AFIO_LOGGING_MEMORY (1024 * 1024)
+#define LLFIO_LOGGING_MEMORY (1024 * 1024)
#endif
#endif
-#if !defined(AFIO_EXPERIMENTAL_STATUS_CODE)
+#if !defined(LLFIO_EXPERIMENTAL_STATUS_CODE)
//! \brief Whether to use SG14 experimental `status_code` instead of `std::error_code`
-#define AFIO_EXPERIMENTAL_STATUS_CODE 0
+#define LLFIO_EXPERIMENTAL_STATUS_CODE 0
#endif
#if defined(_WIN32)
#if !defined(_UNICODE)
-#error AFIO cannot target the ANSI Windows API. Please define _UNICODE to target the Unicode Windows API.
+#error LLFIO cannot target the ANSI Windows API. Please define _UNICODE to target the Unicode Windows API.
#endif
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0600
#elif _WIN32_WINNT < 0x0600
-#error _WIN32_WINNT must at least be set to Windows Vista for AFIO to work
+#error _WIN32_WINNT must at least be set to Windows Vista for LLFIO to work
#endif
#if defined(NTDDI_VERSION) && NTDDI_VERSION < 0x06000000
-#error NTDDI_VERSION must at least be set to Windows Vista for AFIO to work
+#error NTDDI_VERSION must at least be set to Windows Vista for LLFIO to work
#endif
#endif
#ifdef __APPLE__
-#define AFIO_MISSING_PIOV 1
+#define LLFIO_MISSING_PIOV 1
#endif
// Pull in detection of __MINGW64_VERSION_MAJOR
@@ -112,54 +112,54 @@ Distributed under the Boost Software License, Version 1.0.
#include "quickcpplib/include/cpp_feature.h"
#ifndef __cpp_exceptions
-#error AFIO needs C++ exceptions to be turned on
+#error LLFIO needs C++ exceptions to be turned on
#endif
#ifndef __cpp_alias_templates
-#error AFIO needs template alias support in the compiler
+#error LLFIO needs template alias support in the compiler
#endif
#ifndef __cpp_variadic_templates
-#error AFIO needs variadic template support in the compiler
+#error LLFIO needs variadic template support in the compiler
#endif
#if __cpp_constexpr < 201304L && !defined(_MSC_VER)
-#error AFIO needs relaxed constexpr (C++ 14) support in the compiler
+#error LLFIO needs relaxed constexpr (C++ 14) support in the compiler
#endif
#ifndef __cpp_init_captures
-#error AFIO needs lambda init captures support in the compiler (C++ 14)
+#error LLFIO needs lambda init captures support in the compiler (C++ 14)
#endif
#ifndef __cpp_attributes
-#error AFIO needs attributes support in the compiler
+#error LLFIO needs attributes support in the compiler
#endif
#ifndef __cpp_variable_templates
-#error AFIO needs variable template support in the compiler
+#error LLFIO needs variable template support in the compiler
#endif
#ifndef __cpp_generic_lambdas
-#error AFIO needs generic lambda support in the compiler
+#error LLFIO needs generic lambda support in the compiler
#endif
#ifdef __has_include
// clang-format off
#if !__has_include(<filesystem>) && !__has_include(<experimental/filesystem>)
// clang-format on
-#error AFIO needs an implementation of the Filesystem TS in the standard library
+#error LLFIO needs an implementation of the Filesystem TS in the standard library
#endif
#endif
#include "quickcpplib/include/import.h"
-#if defined(AFIO_UNSTABLE_VERSION) && !defined(AFIO_DISABLE_ABI_PERMUTATION)
+#if defined(LLFIO_UNSTABLE_VERSION) && !defined(LLFIO_DISABLE_ABI_PERMUTATION)
#include "../revision.hpp"
-#define AFIO_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(afio_v2, AFIO_PREVIOUS_COMMIT_UNIQUE))
+#define LLFIO_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(llfio_v2, LLFIO_PREVIOUS_COMMIT_UNIQUE))
#else
-#define AFIO_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(afio_v2))
+#define LLFIO_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(llfio_v2))
#endif
-/*! \def AFIO_V2
+/*! \def LLFIO_V2
\ingroup config
-\brief The namespace configuration of this AFIO v2. Consists of a sequence
+\brief The namespace configuration of this LLFIO v2. Consists of a sequence
of bracketed tokens later fused by the preprocessor into namespace and C++ module names.
*/
#if DOXYGEN_IS_IN_THE_HOUSE
-//! The AFIO namespace
-namespace afio_v2_xxx
+//! The LLFIO namespace
+namespace llfio_v2_xxx
{
//! Collection of file system based algorithms
namespace algorithm
@@ -169,53 +169,53 @@ namespace afio_v2_xxx
namespace storage_profile
{
}
- //! Utility routines often useful when using AFIO
+ //! Utility routines often useful when using LLFIO
namespace utils
{
}
}
-/*! \brief The namespace of this AFIO v2 which will be some unknown inline
-namespace starting with `v2_` inside the `boost::afio` namespace.
+/*! \brief The namespace of this LLFIO v2 which will be some unknown inline
+namespace starting with `v2_` inside the `boost::llfio` namespace.
\ingroup config
*/
-#define AFIO_V2_NAMESPACE afio_v2_xxx
-/*! \brief Expands into the appropriate namespace markup to enter the AFIO v2 namespace.
+#define LLFIO_V2_NAMESPACE llfio_v2_xxx
+/*! \brief Expands into the appropriate namespace markup to enter the LLFIO v2 namespace.
\ingroup config
*/
-#define AFIO_V2_NAMESPACE_BEGIN \
- namespace afio_v2_xxx \
+#define LLFIO_V2_NAMESPACE_BEGIN \
+ namespace llfio_v2_xxx \
{
/*! \brief Expands into the appropriate namespace markup to enter the C++ module
-exported AFIO v2 namespace.
+exported LLFIO v2 namespace.
\ingroup config
*/
-#define AFIO_V2_NAMESPACE_EXPORT_BEGIN \
- export namespace afio_v2_xxx \
+#define LLFIO_V2_NAMESPACE_EXPORT_BEGIN \
+ export namespace llfio_v2_xxx \
{
-/*! \brief Expands into the appropriate namespace markup to exit the AFIO v2 namespace.
+/*! \brief Expands into the appropriate namespace markup to exit the LLFIO v2 namespace.
\ingroup config
*/
-#define AFIO_V2_NAMESPACE_END }
-#elif defined(GENERATING_AFIO_MODULE_INTERFACE)
-#define AFIO_V2_NAMESPACE QUICKCPPLIB_BIND_NAMESPACE(AFIO_V2)
-#define AFIO_V2_NAMESPACE_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(AFIO_V2)
-#define AFIO_V2_NAMESPACE_EXPORT_BEGIN QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN(AFIO_V2)
-#define AFIO_V2_NAMESPACE_END QUICKCPPLIB_BIND_NAMESPACE_END(AFIO_V2)
+#define LLFIO_V2_NAMESPACE_END }
+#elif defined(GENERATING_LLFIO_MODULE_INTERFACE)
+#define LLFIO_V2_NAMESPACE QUICKCPPLIB_BIND_NAMESPACE(LLFIO_V2)
+#define LLFIO_V2_NAMESPACE_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(LLFIO_V2)
+#define LLFIO_V2_NAMESPACE_EXPORT_BEGIN QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN(LLFIO_V2)
+#define LLFIO_V2_NAMESPACE_END QUICKCPPLIB_BIND_NAMESPACE_END(LLFIO_V2)
#else
-#define AFIO_V2_NAMESPACE QUICKCPPLIB_BIND_NAMESPACE(AFIO_V2)
-#define AFIO_V2_NAMESPACE_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(AFIO_V2)
-#define AFIO_V2_NAMESPACE_EXPORT_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(AFIO_V2)
-#define AFIO_V2_NAMESPACE_END QUICKCPPLIB_BIND_NAMESPACE_END(AFIO_V2)
+#define LLFIO_V2_NAMESPACE QUICKCPPLIB_BIND_NAMESPACE(LLFIO_V2)
+#define LLFIO_V2_NAMESPACE_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(LLFIO_V2)
+#define LLFIO_V2_NAMESPACE_EXPORT_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(LLFIO_V2)
+#define LLFIO_V2_NAMESPACE_END QUICKCPPLIB_BIND_NAMESPACE_END(LLFIO_V2)
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
class handle;
class file_handle;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Bring in the Boost-lite macros
#include "quickcpplib/include/config.hpp"
-#if AFIO_LOGGING_LEVEL
+#if LLFIO_LOGGING_LEVEL
#include "quickcpplib/include/ringbuffer_log.hpp"
#include "quickcpplib/include/utils/thread.hpp"
#endif
@@ -224,85 +224,85 @@ AFIO_V2_NAMESPACE_END
// clang-format off
#if __has_include(<filesystem>) && __cplusplus >= 202000
#include <filesystem>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace filesystem = std::filesystem;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace filesystem = std::experimental::filesystem;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
#elif __PCPP_ALWAYS_TRUE__
#include <experimental/filesystem>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace filesystem = std::experimental::filesystem;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// clang-format on
#elif defined(_MSC_VER)
#include <filesystem>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace filesystem = std::experimental::filesystem;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#else
#error No <filesystem> implementation found
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
struct path_hasher
{
size_t operator()(const filesystem::path &p) const { return std::hash<filesystem::path::string_type>()(p.native()); }
};
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#include <ctime> // for struct timespec
-// Configure AFIO_DECL
-#if(defined(AFIO_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(AFIO_STATIC_LINK)
+// Configure LLFIO_DECL
+#if(defined(LLFIO_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(LLFIO_STATIC_LINK)
-#if defined(AFIO_SOURCE)
-#define AFIO_DECL QUICKCPPLIB_SYMBOL_EXPORT
-#define AFIO_BUILD_DLL
+#if defined(LLFIO_SOURCE)
+#define LLFIO_DECL QUICKCPPLIB_SYMBOL_EXPORT
+#define LLFIO_BUILD_DLL
#else
-#define AFIO_DECL QUICKCPPLIB_SYMBOL_IMPORT
+#define LLFIO_DECL QUICKCPPLIB_SYMBOL_IMPORT
#endif
#else
-#define AFIO_DECL
+#define LLFIO_DECL
#endif // building a shared library
-// Configure AFIO_THREAD_LOCAL
-#ifndef AFIO_THREAD_LOCAL_IS_CXX11
-#define AFIO_THREAD_LOCAL_IS_CXX11 QUICKCPPLIB_THREAD_LOCAL_IS_CXX11
+// Configure LLFIO_THREAD_LOCAL
+#ifndef LLFIO_THREAD_LOCAL_IS_CXX11
+#define LLFIO_THREAD_LOCAL_IS_CXX11 QUICKCPPLIB_THREAD_LOCAL_IS_CXX11
#endif
-#ifndef AFIO_THREAD_LOCAL
-#define AFIO_THREAD_LOCAL QUICKCPPLIB_THREAD_LOCAL
+#ifndef LLFIO_THREAD_LOCAL
+#define LLFIO_THREAD_LOCAL QUICKCPPLIB_THREAD_LOCAL
#endif
-#ifndef AFIO_TEMPLATE
-#define AFIO_TEMPLATE(...) QUICKCPPLIB_TEMPLATE(__VA_ARGS__)
+#ifndef LLFIO_TEMPLATE
+#define LLFIO_TEMPLATE(...) QUICKCPPLIB_TEMPLATE(__VA_ARGS__)
#endif
-#ifndef AFIO_TREQUIRES
-#define AFIO_TREQUIRES(...) QUICKCPPLIB_TREQUIRES(__VA_ARGS__)
+#ifndef LLFIO_TREQUIRES
+#define LLFIO_TREQUIRES(...) QUICKCPPLIB_TREQUIRES(__VA_ARGS__)
#endif
-#ifndef AFIO_TEXPR
-#define AFIO_TEXPR(...) QUICKCPPLIB_TEXPR(__VA_ARGS__)
+#ifndef LLFIO_TEXPR
+#define LLFIO_TEXPR(...) QUICKCPPLIB_TEXPR(__VA_ARGS__)
#endif
-#ifndef AFIO_TPRED
-#define AFIO_TPRED(...) QUICKCPPLIB_TPRED(__VA_ARGS__)
+#ifndef LLFIO_TPRED
+#define LLFIO_TPRED(...) QUICKCPPLIB_TPRED(__VA_ARGS__)
#endif
-#ifndef AFIO_REQUIRES
-#define AFIO_REQUIRES(...) QUICKCPPLIB_REQUIRES(__VA_ARGS__)
+#ifndef LLFIO_REQUIRES
+#define LLFIO_REQUIRES(...) QUICKCPPLIB_REQUIRES(__VA_ARGS__)
#endif
// A unique identifier generating macro
-#define AFIO_GLUE2(x, y) x##y
-#define AFIO_GLUE(x, y) AFIO_GLUE2(x, y)
-#define AFIO_UNIQUE_NAME AFIO_GLUE(__t, __COUNTER__)
+#define LLFIO_GLUE2(x, y) x##y
+#define LLFIO_GLUE(x, y) LLFIO_GLUE2(x, y)
+#define LLFIO_UNIQUE_NAME LLFIO_GLUE(__t, __COUNTER__)
// Used to tag functions which need to be made free by the AST tool
-#ifndef AFIO_MAKE_FREE_FUNCTION
+#ifndef LLFIO_MAKE_FREE_FUNCTION
#if 0 //__cplusplus >= 201700 // makes annoying warnings
-#define AFIO_MAKE_FREE_FUNCTION [[afio::make_free_function]]
+#define LLFIO_MAKE_FREE_FUNCTION [[llfio::make_free_function]]
#else
-#define AFIO_MAKE_FREE_FUNCTION
+#define LLFIO_MAKE_FREE_FUNCTION
#endif
#endif
@@ -310,57 +310,57 @@ AFIO_V2_NAMESPACE_END
#include "quickcpplib/include/bitfield.hpp"
// Bring in scoped undo
#include "quickcpplib/include/scoped_undo.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
using QUICKCPPLIB_NAMESPACE::scoped_undo::undoer;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Bring in a span implementation
#include "quickcpplib/include/span.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
using namespace QUICKCPPLIB_NAMESPACE::span;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Bring in an optional implementation
#include "quickcpplib/include/optional.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
using namespace QUICKCPPLIB_NAMESPACE::optional;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Bring in a byte implementation
#include "quickcpplib/include/byte.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
using QUICKCPPLIB_NAMESPACE::byte::byte;
using QUICKCPPLIB_NAMESPACE::byte::to_byte;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Bring in a string_view implementation
#include "quickcpplib/include/string_view.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
using namespace QUICKCPPLIB_NAMESPACE::string_view;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Bring in a persistent implementation
#include "quickcpplib/include/persistent.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
using namespace QUICKCPPLIB_NAMESPACE::persistence;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace detail
{
// Used to cast an unknown input to some unsigned integer
- AFIO_TEMPLATE(class T, class U)
- AFIO_TREQUIRES(AFIO_TPRED(std::is_unsigned<T>::value && !std::is_same<std::decay_t<U>, std::nullptr_t>::value))
+ LLFIO_TEMPLATE(class T, class U)
+ LLFIO_TREQUIRES(LLFIO_TPRED(std::is_unsigned<T>::value && !std::is_same<std::decay_t<U>, std::nullptr_t>::value))
inline T unsigned_integer_cast(U &&v) { return static_cast<T>(v); }
- AFIO_TEMPLATE(class T)
- AFIO_TREQUIRES(AFIO_TPRED(std::is_unsigned<T>::value))
+ LLFIO_TEMPLATE(class T)
+ LLFIO_TREQUIRES(LLFIO_TPRED(std::is_unsigned<T>::value))
inline T unsigned_integer_cast(std::nullptr_t /* unused */) { return static_cast<T>(0); }
- AFIO_TEMPLATE(class T, class U)
- AFIO_TREQUIRES(AFIO_TPRED(std::is_unsigned<T>::value))
+ LLFIO_TEMPLATE(class T, class U)
+ LLFIO_TREQUIRES(LLFIO_TPRED(std::is_unsigned<T>::value))
inline T unsigned_integer_cast(U *v) { return static_cast<T>(reinterpret_cast<uintptr_t>(v)); }
} // namespace detail
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace detail
{
@@ -445,18 +445,18 @@ namespace win
using dword = unsigned long;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#if 0
///////////////////////////////////////////////////////////////////////////////
// Auto library naming
-#if !defined(AFIO_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(AFIO_NO_LIB) && !AFIO_STANDALONE && !AFIO_HEADERS_ONLY
+#if !defined(LLFIO_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(LLFIO_NO_LIB) && !LLFIO_STANDALONE && !LLFIO_HEADERS_ONLY
-#define BOOST_LIB_NAME boost_afio
+#define BOOST_LIB_NAME boost_llfio
// tell the auto-link code to select a dll when required:
-#if defined(BOOST_ALL_DYN_LINK) || defined(AFIO_DYN_LINK)
+#if defined(BOOST_ALL_DYN_LINK) || defined(LLFIO_DYN_LINK)
#define BOOST_DYN_LINK
#endif
@@ -469,26 +469,26 @@ AFIO_V2_NAMESPACE_END
//#define BOOST_THREAD_PROVIDES_VARIADIC_THREAD
//#define BOOST_THREAD_DONT_PROVIDE_FUTURE
//#define BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
-#if AFIO_HEADERS_ONLY == 1 && !defined(AFIO_SOURCE)
+#if LLFIO_HEADERS_ONLY == 1 && !defined(LLFIO_SOURCE)
/*! \brief Expands into the appropriate markup to declare an `extern`
-function exported from the AFIO DLL if not building headers only.
+function exported from the LLFIO DLL if not building headers only.
\ingroup config
*/
-#define AFIO_HEADERS_ONLY_FUNC_SPEC inline
+#define LLFIO_HEADERS_ONLY_FUNC_SPEC inline
/*! \brief Expands into the appropriate markup to declare a class member
-function exported from the AFIO DLL if not building headers only.
+function exported from the LLFIO DLL if not building headers only.
\ingroup config
*/
-#define AFIO_HEADERS_ONLY_MEMFUNC_SPEC inline
+#define LLFIO_HEADERS_ONLY_MEMFUNC_SPEC inline
/*! \brief Expands into the appropriate markup to declare a virtual class member
-function exported from the AFIO DLL if not building headers only.
+function exported from the LLFIO DLL if not building headers only.
\ingroup config
*/
-#define AFIO_HEADERS_ONLY_VIRTUAL_SPEC inline virtual
+#define LLFIO_HEADERS_ONLY_VIRTUAL_SPEC inline virtual
#else
-#define AFIO_HEADERS_ONLY_FUNC_SPEC extern AFIO_DECL
-#define AFIO_HEADERS_ONLY_MEMFUNC_SPEC
-#define AFIO_HEADERS_ONLY_VIRTUAL_SPEC virtual
+#define LLFIO_HEADERS_ONLY_FUNC_SPEC extern LLFIO_DECL
+#define LLFIO_HEADERS_ONLY_MEMFUNC_SPEC
+#define LLFIO_HEADERS_ONLY_VIRTUAL_SPEC virtual
#endif
#endif
diff --git a/include/llfio/v2.0/deadline.h b/include/llfio/v2.0/deadline.h
new file mode 100644
index 00000000..c7681d52
--- /dev/null
+++ b/include/llfio/v2.0/deadline.h
@@ -0,0 +1,129 @@
+/* Specifies a time deadline
+(C) 2015-2017 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
+File Created: Dec 2015
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef LLFIO_DEADLINE_H
+#define LLFIO_DEADLINE_H
+
+#include <stdbool.h> // NOLINT
+#include <time.h> // NOLINT
+
+//! \file deadline.h Provides struct deadline
+
+#if defined(__cplusplus) || DOXYGEN_IS_IN_THE_HOUSE
+#ifndef LLFIO_CONFIG_HPP
+#error You must include the master llfio.hpp, not individual header files directly
+#endif
+#include "config.hpp"
+#include <stdexcept>
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
+#define LLFIO_DEADLINE_NAME deadline
+#else
+#define LLFIO_DEADLINE_NAME boost_llfio_deadline
+#endif
+
+/*! \struct deadline
+\brief A time deadline in either relative-to-now or absolute (system clock) terms
+*/
+struct LLFIO_DEADLINE_NAME
+{
+ //! True if deadline does not change with system clock changes
+ bool steady; // NOLINT
+ union {
+ //! System time from timespec_get(&ts, TIME_UTC)
+ struct timespec utc; // NOLINT
+ //! Nanosecond ticks from start of operation
+ unsigned long long nsecs; // NOLINT
+ };
+#ifdef __cplusplus
+ constexpr deadline() // NOLINT
+ : steady(false),
+ utc{0, 0}
+ {
+ }
+ //! True if deadline is valid
+ constexpr explicit operator bool() const noexcept { return steady || utc.tv_sec != 0; }
+ //! Implicitly construct a deadline from a system clock time point
+ deadline(std::chrono::system_clock::time_point tp) // NOLINT
+ : steady(false),
+ utc{0, 0}
+ {
+ std::chrono::seconds secs(std::chrono::system_clock::to_time_t(tp));
+ utc.tv_sec = secs.count();
+ std::chrono::system_clock::time_point _tp(std::chrono::system_clock::from_time_t(utc.tv_sec));
+ utc.tv_nsec = static_cast<long>(std::chrono::duration_cast<std::chrono::nanoseconds>(tp - _tp).count());
+ }
+ //! Implicitly construct a deadline from a duration from now
+ template <class Rep, class Period>
+ constexpr deadline(std::chrono::duration<Rep, Period> d) // NOLINT
+ : steady(true),
+ nsecs(0)
+ {
+ std::chrono::nanoseconds _nsecs = std::chrono::duration_cast<std::chrono::nanoseconds>(d);
+ // Negative durations are zero duration
+ if(_nsecs.count() > 0)
+ {
+ nsecs = _nsecs.count();
+ }
+ else
+ {
+ nsecs = 0;
+ }
+ }
+ //! Returns a system_clock::time_point for this deadline
+ std::chrono::system_clock::time_point to_time_point() const
+ {
+ if(steady)
+ {
+ throw std::invalid_argument("Not a UTC deadline!"); // NOLINT
+ }
+ std::chrono::system_clock::time_point tp(std::chrono::system_clock::from_time_t(utc.tv_sec));
+ tp += std::chrono::duration_cast<std::chrono::system_clock::duration>(std::chrono::nanoseconds(utc.tv_nsec));
+ return tp;
+ }
+#endif
+};
+
+#define LLFIO_DEADLINE_TO_PARTIAL_DEADLINE(nd, d) \
+ if(d) \
+ { \
+ if((d).steady) \
+ { \
+ (nd).steady = true; \
+ std::chrono::nanoseconds ns = std::chrono::duration_cast<std::chrono::nanoseconds>((began_steady + std::chrono::nanoseconds((d).nsecs)) - std::chrono::steady_clock::now()); \
+ if(ns.count() < 0) \
+ (nd).nsecs = 0; \
+ else \
+ (nd).nsecs = ns.count(); \
+ } \
+ else \
+ (nd) = (d); \
+ }
+
+
+#undef LLFIO_DEADLINE_NAME
+#if defined(__cplusplus) || DOXYGEN_IS_IN_THE_HOUSE
+LLFIO_V2_NAMESPACE_END
+#endif
+
+#endif
diff --git a/include/afio/v2.0/detail/impl/cached_parent_handle_adapter.ipp b/include/llfio/v2.0/detail/impl/cached_parent_handle_adapter.ipp
index bb2d0fbe..e966a25c 100644
--- a/include/afio/v2.0/detail/impl/cached_parent_handle_adapter.ipp
+++ b/include/llfio/v2.0/detail/impl/cached_parent_handle_adapter.ipp
@@ -27,7 +27,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <mutex>
#include <unordered_map>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -44,7 +44,7 @@ namespace algorithm
static cached_path_handle_map_ map;
return map;
}
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<filesystem::path> cached_path_handle::current_path(const filesystem::path &append) noexcept
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<filesystem::path> cached_path_handle::current_path(const filesystem::path &append) noexcept
{
try
{
@@ -55,7 +55,7 @@ namespace algorithm
{
std::string msg("cached_path_handle::current_path() failed to retrieve current path of cached handle due to ");
msg.append(ret.error().message().c_str());
- AFIO_LOG_WARN(nullptr, msg.c_str());
+ LLFIO_LOG_WARN(nullptr, msg.c_str());
}
else if(!ret.value().empty() && ret.value() != _lastpath)
{
@@ -70,7 +70,7 @@ namespace algorithm
return error_from_exception();
}
}
- AFIO_HEADERS_ONLY_FUNC_SPEC std::pair<cached_path_handle_ptr, filesystem::path> get_cached_path_handle(const path_handle &base, path_view path)
+ LLFIO_HEADERS_ONLY_FUNC_SPEC std::pair<cached_path_handle_ptr, filesystem::path> get_cached_path_handle(const path_handle &base, path_view path)
{
path_view leaf(path.filename());
path.remove_filename();
@@ -148,4 +148,4 @@ namespace algorithm
} // namespace detail
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/path_discovery.ipp b/include/llfio/v2.0/detail/impl/path_discovery.ipp
index 1fd3588f..3369bd21 100644
--- a/include/afio/v2.0/detail/impl/path_discovery.ipp
+++ b/include/llfio/v2.0/detail/impl/path_discovery.ipp
@@ -31,7 +31,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <regex>
#include <vector>
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace path_discovery
{
@@ -87,7 +87,7 @@ namespace path_discovery
std::vector<std::pair<discovered_path::source_type, _store::_discovered_path>> raw = _all_temporary_directories();
if(raw.empty())
{
- AFIO_LOG_FATAL(nullptr, "path_discovery::all_temporary_directories() sees no possible temporary directories, something has gone very wrong");
+ LLFIO_LOG_FATAL(nullptr, "path_discovery::all_temporary_directories() sees no possible temporary directories, something has gone very wrong");
abort();
}
for(size_t n = 0; n < raw.size(); n++)
@@ -115,11 +115,11 @@ namespace path_discovery
{
std::string msg("path_discovery::all_temporary_directories() saw exception thrown: ");
msg.append(e.what());
- AFIO_LOG_WARN(nullptr, msg.c_str());
+ LLFIO_LOG_WARN(nullptr, msg.c_str());
}
catch(...)
{
- AFIO_LOG_WARN(nullptr, "path_discovery::all_temporary_directories() saw unknown exception throw");
+ LLFIO_LOG_WARN(nullptr, "path_discovery::all_temporary_directories() saw unknown exception throw");
}
return ps.all;
}
@@ -157,12 +157,12 @@ namespace path_discovery
auto _fh = file_handle::random_file(ps._all[n].h, file_handle::mode::write, file_handle::caching::temporary, file_handle::flag::unlink_on_first_close);
if(!_fh)
{
-#if AFIO_LOGGING_LEVEL >= 3
+#if LLFIO_LOGGING_LEVEL >= 3
std::string msg("path_discovery::verified_temporary_directories() failed to create a file in ");
msg.append(ps._all[n].path.u8string());
msg.append(" due to ");
msg.append(_fh.error().message().c_str());
- AFIO_LOG_WARN(nullptr, msg.c_str());
+ LLFIO_LOG_WARN(nullptr, msg.c_str());
#endif
ps._all[n].h = {};
continue;
@@ -170,7 +170,7 @@ namespace path_discovery
ps.all[n].stat = stat_t(nullptr);
if(!ps.all[n].stat->fill(ps._all[n].h))
{
- AFIO_LOG_WARN(nullptr, "path_discovery::verified_temporary_directories() failed to stat an open handle to a temp directory");
+ LLFIO_LOG_WARN(nullptr, "path_discovery::verified_temporary_directories() failed to stat an open handle to a temp directory");
ps.all[n].stat = {};
ps._all[n].h = {};
continue;
@@ -183,12 +183,12 @@ namespace path_discovery
}
else
{
-#if AFIO_LOGGING_LEVEL >= 3
+#if LLFIO_LOGGING_LEVEL >= 3
std::string msg("path_discovery::verified_temporary_directories() failed to statfs the temp directory ");
msg.append(ps._all[n].path.u8string());
msg.append(" due to ");
msg.append(statfsres.error().message().c_str());
- AFIO_LOG_WARN(nullptr, msg.c_str());
+ LLFIO_LOG_WARN(nullptr, msg.c_str());
#endif
ps.all[n].stat = {};
ps._all[n].h = {};
@@ -201,7 +201,7 @@ namespace path_discovery
ps.verified = span<discovered_path>(ps.all.data(), it - ps.all.begin());
if(ps.verified.empty())
{
- AFIO_LOG_FATAL(nullptr, "path_discovery::verified_temporary_directories() could not find at least one writable temporary directory");
+ LLFIO_LOG_FATAL(nullptr, "path_discovery::verified_temporary_directories() could not find at least one writable temporary directory");
abort();
}
@@ -226,12 +226,12 @@ namespace path_discovery
{
std::string msg("path_discovery::verified_temporary_directories() saw exception thrown: ");
msg.append(e.what());
- AFIO_LOG_FATAL(nullptr, msg.c_str());
+ LLFIO_LOG_FATAL(nullptr, msg.c_str());
abort();
}
catch(...)
{
- AFIO_LOG_FATAL(nullptr, "path_discovery::verified_temporary_directories() saw unknown exception throw");
+ LLFIO_LOG_FATAL(nullptr, "path_discovery::verified_temporary_directories() saw unknown exception throw");
abort();
}
return ps.verified;
@@ -251,12 +251,12 @@ namespace path_discovery
}
} // namespace path_discovery
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#define AFIO_PATH_DISCOVERY_INCLUDING
+#define LLFIO_PATH_DISCOVERY_INCLUDING
#ifdef _WIN32
#include "windows/path_discovery.ipp"
#else
#include "posix/path_discovery.ipp"
#endif
-#undef AFIO_PATH_DISCOVERY_INCLUDING
+#undef LLFIO_PATH_DISCOVERY_INCLUDING
diff --git a/include/afio/v2.0/detail/impl/posix/async_file_handle.ipp b/include/llfio/v2.0/detail/impl/posix/async_file_handle.ipp
index 59f10eae..4a3a8652 100644
--- a/include/afio/v2.0/detail/impl/posix/async_file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/async_file_handle.ipp
@@ -26,15 +26,15 @@ Distributed under the Boost Software License, Version 1.0.
#include <fcntl.h>
#include <unistd.h>
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
#include <aio.h>
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_handle::barrier(async_file_handle::io_request<async_file_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
optional<io_result<const_buffers_type>> ret;
OUTCOME_TRY(io_state, async_barrier(reqs, [&ret](async_file_handle *, io_result<const_buffers_type> &result) { ret = result; }, wait_for_device, and_metadata));
(void) io_state;
@@ -51,7 +51,7 @@ async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_h
#ifndef NDEBUG
if(!ret && t && !t.value())
{
- AFIO_LOG_FATAL(_v.fd, "async_file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(_v.fd, "async_file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -64,7 +64,7 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
// Need to keep a set of aiocbs matching the scatter-gather buffers
struct state_type : public _erased_io_state_type
{
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
struct aiocb aiocbs[1]{};
#else
#error todo
@@ -80,10 +80,10 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
, completion(nullptr)
{
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC _erased_completion_handler *erased_completion_handler() noexcept final { return completion; }
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void _system_io_completion(long errcode, long bytes_transferred, void *internal_state) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC _erased_completion_handler *erased_completion_handler() noexcept final { return completion; }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void _system_io_completion(long errcode, long bytes_transferred, void *internal_state) noexcept final
{
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
auto **_paiocb = static_cast<struct aiocb **>(internal_state);
struct aiocb *aiocb = *_paiocb;
assert(aiocb >= aiocbs && aiocb < aiocbs + this->items);
@@ -101,17 +101,17 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
else
{
// Figure out which i/o I am and update the buffer in question
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
size_t idx = aiocb - aiocbs;
#else
#error todo
#endif
if(idx >= this->items)
{
- AFIO_LOG_FATAL(0, "file_handle::io_state::operator() called with invalid index");
+ LLFIO_LOG_FATAL(0, "file_handle::io_state::operator() called with invalid index");
std::terminate();
}
- result.value()[idx].len = bytes_transferred;
+ result.value()[idx] = {result.value()[idx].data(), (size_type) bytes_transferred};
}
}
this->parent->service()->_work_done();
@@ -121,14 +121,14 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
(*completion)(this);
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~state_type() final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~state_type() final
{
// Do we need to cancel pending i/o?
if(this->items_to_go)
{
for(size_t n = 0; n < this->items; n++)
{
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
int ret = aio_cancel(this->parent->native_handle().fd, aiocbs + n);
(void) ret;
#if 0
@@ -157,12 +157,12 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
#ifndef NDEBUG
if(res.has_error())
{
- AFIO_LOG_FATAL(0, "file_handle: io_service failed");
+ LLFIO_LOG_FATAL(0, "file_handle: io_service failed");
std::terminate();
}
if(!res.value())
{
- AFIO_LOG_FATAL(0, "file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(0, "file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -178,7 +178,7 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
return errc::not_enough_memory;
}
size_t items(reqs.buffers.size());
-#if AFIO_USE_POSIX_AIO && defined(AIO_LISTIO_MAX)
+#if LLFIO_USE_POSIX_AIO && defined(AIO_LISTIO_MAX)
// If this i/o could never be done atomically, reject
if(items > AIO_LISTIO_MAX)
return errc::invalid_argument;
@@ -191,9 +191,9 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
// feed more than AIO_LISTIO_MAX items to aio_suspend
// it does NOT return EINVAL as specified, but rather
// simply marks all items past AIO_LISTIO_MAX as failed
- // with EAGAIN. That punishes performance for AFIO
+ // with EAGAIN. That punishes performance for LLFIO
// because we loop setting up and tearing down
- // the handlers, so if we would overload afio_suspend,
+ // the handlers, so if we would overload llfio_suspend,
// better to error out now rather that later in io_service.
if(service()->_aiocbsv.size() + items > AIO_LISTIO_MAX)
{
@@ -223,20 +223,20 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
out = std::move(reqs.buffers);
for(size_t n = 0; n < items; n++)
{
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
#ifndef NDEBUG
if(_v.requires_aligned_io())
{
assert((offset & 511) == 0);
- assert(((uintptr_t) out[n].data & 511) == 0);
- assert((out[n].len & 511) == 0);
+ assert(((uintptr_t) out[n].data() & 511) == 0);
+ assert((out[n].size() & 511) == 0);
}
#endif
struct aiocb *aiocb = state->aiocbs + n;
aiocb->aio_fildes = _v.fd;
aiocb->aio_offset = offset;
- aiocb->aio_buf = reinterpret_cast<void *>(const_cast<byte *>(out[n].data));
- aiocb->aio_nbytes = out[n].len;
+ aiocb->aio_buf = reinterpret_cast<void *>(const_cast<byte *>(out[n].data()));
+ aiocb->aio_nbytes = out[n].size();
aiocb->aio_sigevent.sigev_notify = SIGEV_NONE;
aiocb->aio_sigevent.sigev_value.sival_ptr = reinterpret_cast<void *>(state);
switch(operation)
@@ -259,14 +259,14 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
#else
#error todo
#endif
- offset += out[n].len;
+ offset += out[n].size();
++state->items_to_go;
}
int ret = 0;
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
if(service()->using_kqueues())
{
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_COMPILE_KQUEUES
// Only issue one kqueue event when entire scatter-gather has completed
struct _sigev = {0};
#error todo
@@ -326,7 +326,7 @@ result<async_file_handle::io_state_ptr> async_file_handle::_begin_io(span<char>
async_file_handle::io_result<async_file_handle::buffers_type> async_file_handle::read(async_file_handle::io_request<async_file_handle::buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
optional<io_result<buffers_type>> ret;
OUTCOME_TRY(io_state, async_read(reqs, [&ret](async_file_handle *, io_result<buffers_type> &result) { ret = result; }));
(void) io_state;
@@ -343,7 +343,7 @@ async_file_handle::io_result<async_file_handle::buffers_type> async_file_handle:
#ifndef NDEBUG
if(!ret && t && !t.value())
{
- AFIO_LOG_FATAL(_v.fd, "async_file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(_v.fd, "async_file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -353,7 +353,7 @@ async_file_handle::io_result<async_file_handle::buffers_type> async_file_handle:
async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_handle::write(async_file_handle::io_request<async_file_handle::const_buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
optional<io_result<const_buffers_type>> ret;
OUTCOME_TRY(io_state, async_write(reqs, [&ret](async_file_handle *, io_result<const_buffers_type> &result) { ret = result; }));
(void) io_state;
@@ -370,7 +370,7 @@ async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_h
#ifndef NDEBUG
if(!ret && t && !t.value())
{
- AFIO_LOG_FATAL(_v.fd, "async_file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(_v.fd, "async_file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -378,4 +378,4 @@ async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_h
return *ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/directory_handle.ipp b/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
index b42ae784..247f030b 100644
--- a/include/afio/v2.0/detail/impl/posix/directory_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
@@ -27,9 +27,9 @@ http://www.boost.org/LICENSE_1_0.txt)
#ifdef QUICKCPPLIB_ENABLE_VALGRIND
#include "../../../quickcpplib/valgrind/memcheck.h"
-#define AFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(a, b) VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE((a), (b))
+#define LLFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(a, b) VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE((a), (b))
#else
-#define AFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(a, b)
+#define LLFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(a, b)
#endif
#include <dirent.h> /* Defines DT_* constants */
@@ -37,7 +37,7 @@ http://www.boost.org/LICENSE_1_0.txt)
#include <sys/stat.h>
#include <sys/syscall.h>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<directory_handle> directory_handle::directory(const path_handle &base, path_view_type path, mode _mode, creation _creation, caching _caching, flag flags) noexcept
{
@@ -47,7 +47,7 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
}
result<directory_handle> ret(directory_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::directory;
// POSIX does not permit directory opens with O_RDWR like Windows, so silently convert to read
if(_mode == mode::attr_write)
@@ -128,7 +128,7 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
result<directory_handle> directory_handle::clone(mode mode_, caching caching_, deadline d) const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// Fast path
if(mode_ == mode::unchanged && caching_ == caching::unchanged)
{
@@ -196,9 +196,9 @@ result<directory_handle> directory_handle::clone(mode mode_, caching caching_, d
}
}
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> directory_handle::clone_to_path_handle() const noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> directory_handle::clone_to_path_handle() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
result<path_handle> ret(path_handle(native_handle_type(), _caching, _flags));
ret.value()._v.behaviour = _v.behaviour;
ret.value()._v.fd = ::fcntl(_v.fd, F_DUPFD_CLOEXEC);
@@ -211,7 +211,7 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> directory_handle::clone_to_pa
result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_type &&tofill, path_view_type glob, filter /*unused*/, span<char> kernelbuffer) const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(tofill.empty())
{
return enumerate_info{std::move(tofill), stat_t::want::none, false};
@@ -353,7 +353,7 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
tofill._resize(0);
return enumerate_info{std::move(tofill), default_stat_contents, true};
}
- AFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, bytes); // NOLINT
+ LLFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, bytes); // NOLINT
size_t n = 0;
for(dirent *dent = buffer;; dent = reinterpret_cast<dirent *>(reinterpret_cast<uintptr_t>(dent) + dent->d_reclen))
{
@@ -421,4 +421,4 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/file_handle.ipp b/include/llfio/v2.0/detail/impl/posix/file_handle.ipp
index 7dcf286b..7972f16b 100644
--- a/include/afio/v2.0/detail/impl/posix/file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/file_handle.ipp
@@ -26,13 +26,13 @@ Distributed under the Boost Software License, Version 1.0.
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<file_handle> file_handle::file(const path_handle &base, file_handle::path_view_type path, file_handle::mode _mode, file_handle::creation _creation, file_handle::caching _caching, file_handle::flag flags) noexcept
{
result<file_handle> ret(file_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::file;
OUTCOME_TRY(attribs, attribs_from_handle_mode_caching_and_flags(nativeh, _mode, _creation, _caching, flags));
path_view::c_str zpath(path);
@@ -78,7 +78,7 @@ result<file_handle> file_handle::temp_inode(const path_handle &dirh, mode _mode,
flags |= flag::unlink_on_first_close | flag::disable_safety_unlinks;
result<file_handle> ret(file_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::file;
// Open file exclusively to prevent collision
OUTCOME_TRY(attribs, attribs_from_handle_mode_caching_and_flags(nativeh, _mode, creation::only_if_not_exist, _caching, flags));
@@ -132,7 +132,7 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(fil
{
(void) wait_for_device;
(void) and_metadata;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(d)
{
return errc::not_supported;
@@ -145,7 +145,7 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(fil
// empty buffers means bytes = 0 which means sync entire file
for(const auto &req : reqs.buffers)
{
- bytes += req.len;
+ bytes += req.size();
}
unsigned flags = SYNC_FILE_RANGE_WRITE; // start writing all dirty pages in range now
if(wait_for_device)
@@ -190,7 +190,7 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(fil
result<file_handle> file_handle::clone(mode mode_, caching caching_, deadline d) const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// Fast path
if(mode_ == mode::unchanged)
{
@@ -334,7 +334,7 @@ result<file_handle> file_handle::clone(mode mode_, caching caching_, deadline d)
result<file_handle::extent_type> file_handle::maximum_extent() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
struct stat s
{
};
@@ -348,7 +348,7 @@ result<file_handle::extent_type> file_handle::maximum_extent() const noexcept
result<file_handle::extent_type> file_handle::truncate(file_handle::extent_type newsize) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(ftruncate(_v.fd, newsize) < 0)
{
return posix_error();
@@ -362,7 +362,7 @@ result<file_handle::extent_type> file_handle::truncate(file_handle::extent_type
result<std::vector<std::pair<file_handle::extent_type, file_handle::extent_type>>> file_handle::extents() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
try
{
std::vector<std::pair<file_handle::extent_type, file_handle::extent_type>> out;
@@ -447,7 +447,7 @@ result<std::vector<std::pair<file_handle::extent_type, file_handle::extent_type>
result<file_handle::extent_type> file_handle::zero(file_handle::extent_type offset, file_handle::extent_type bytes, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
#if defined(__linux__)
if(-1 == fallocate(_v.fd, 0x02 /*FALLOC_FL_PUNCH_HOLE*/ | 0x01 /*FALLOC_FL_KEEP_SIZE*/, offset, bytes))
{
@@ -464,7 +464,7 @@ result<file_handle::extent_type> file_handle::zero(file_handle::extent_type offs
auto *buffer = static_cast<byte *>(alloca(bytes));
memset(buffer, 0, bytes);
OUTCOME_TRY(written, write(offset, {{buffer, bytes}}, d));
- return written[0].len;
+ return written[0].size();
}
try
{
@@ -477,9 +477,9 @@ result<file_handle::extent_type> file_handle::zero(file_handle::extent_type offs
{
auto towrite = (bytes < blocksize) ? bytes : blocksize;
OUTCOME_TRY(written, write(offset, {{buffer, towrite}}, d));
- offset += written[0].len;
- bytes -= written[0].len;
- ret += written[0].len;
+ offset += written[0].size();
+ bytes -= written[0].size();
+ ret += written[0].size();
}
return ret;
}
@@ -489,4 +489,4 @@ result<file_handle::extent_type> file_handle::zero(file_handle::extent_type offs
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/fs_handle.ipp b/include/llfio/v2.0/detail/impl/posix/fs_handle.ipp
index 27f7673f..9457e55b 100644
--- a/include/afio/v2.0/detail/impl/posix/fs_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/fs_handle.ipp
@@ -29,7 +29,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <climits> // for PATH_MAX
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<void> fs_handle::_fetch_inode() const noexcept
{
@@ -40,121 +40,113 @@ result<void> fs_handle::_fetch_inode() const noexcept
return success();
}
-inline result<path_handle> containing_directory(optional<std::reference_wrapper<filesystem::path>> out_filename, const handle &h, const fs_handle &fsh, deadline d) noexcept
+namespace detail
{
- std::chrono::steady_clock::time_point began_steady;
- std::chrono::system_clock::time_point end_utc;
- if(d)
+ result<path_handle> containing_directory(optional<std::reference_wrapper<filesystem::path>> out_filename, const handle &h, const fs_handle &fsh, deadline d) noexcept
{
- if(d.steady)
+ std::chrono::steady_clock::time_point began_steady;
+ std::chrono::system_clock::time_point end_utc;
+ if(d)
{
- began_steady = std::chrono::steady_clock::now();
- }
- else
- {
- end_utc = d.to_time_point();
- }
- }
- try
- {
- for(;;)
- {
- // Get current path for handle and open its containing dir
- OUTCOME_TRY(_currentpath, h.current_path());
- // If current path is empty, it's been deleted
- if(_currentpath.empty())
+ if(d.steady)
{
- return errc::no_such_file_or_directory;
+ began_steady = std::chrono::steady_clock::now();
}
- // Split the path into root and leafname
- path_view currentpath(_currentpath);
- path_view filename = currentpath.filename();
- currentpath.remove_filename();
- // Zero terminate the root path so it doesn't get copied later
- const_cast<filesystem::path::string_type &>(_currentpath.native())[currentpath.native_size()] = 0;
- auto currentdirh_ = path_handle::path(currentpath);
- if(!currentdirh_)
+ else
{
- continue;
+ end_utc = d.to_time_point();
}
- path_handle currentdirh = std::move(currentdirh_.value());
- if(h.flags() & handle::flag::disable_safety_unlinks)
+ }
+ try
+ {
+ for(;;)
{
- if(out_filename)
+ // Get current path for handle and open its containing dir
+ OUTCOME_TRY(_currentpath, h.current_path());
+ // If current path is empty, it's been deleted
+ if(_currentpath.empty())
{
- out_filename->get() = filename.path();
+ return errc::no_such_file_or_directory;
}
- return success(std::move(currentdirh));
- }
- // Open the same file name, and compare dev and inode
- path_view::c_str zpath(filename);
- int fd = ::openat(currentdirh.native_handle().fd, zpath.buffer, O_CLOEXEC);
- if(fd == -1)
- {
- if(ENOENT == errno)
+ // Split the path into root and leafname
+ path_view currentpath(_currentpath);
+ path_view filename = currentpath.filename();
+ currentpath.remove_filename();
+ // Zero terminate the root path so it doesn't get copied later
+ const_cast<filesystem::path::string_type &>(_currentpath.native())[currentpath.native_size()] = 0;
+ auto currentdirh_ = path_handle::path(currentpath);
+ if(!currentdirh_)
{
continue;
}
- return posix_error();
- }
- auto unfd = undoer([fd] { ::close(fd); });
- (void) unfd;
- struct stat s
- {
- };
- if(-1 == ::fstat(fd, &s))
- {
- continue;
- }
- // If the same, we know for a fact that this is the correct containing dir for now at least
- if(static_cast<fs_handle::dev_t>(s.st_dev) == fsh.st_dev() && s.st_ino == fsh.st_ino())
- {
- if(out_filename)
+ path_handle currentdirh = std::move(currentdirh_.value());
+ if((h.flags() & handle::flag::disable_safety_unlinks) != 0)
{
- out_filename->get() = filename.path();
+ if(out_filename)
+ {
+ out_filename->get() = filename.path();
+ }
+ return success(std::move(currentdirh));
}
- return success(std::move(currentdirh));
- }
- // Check timeout
- if(d)
- {
- if(d.steady)
+ // stat the same file name, and compare dev and inode
+ path_view::c_str zpath(filename);
+ struct stat s
+ {
+ };
+ if(-1 == ::fstatat(currentdirh.native_handle().fd, zpath.buffer, &s, AT_SYMLINK_NOFOLLOW))
+ {
+ continue;
+ }
+ // If the same, we know for a fact that this is the correct containing dir for now at least
+ if(static_cast<fs_handle::dev_t>(s.st_dev) == fsh.st_dev() && s.st_ino == fsh.st_ino())
{
- if(std::chrono::steady_clock::now() >= (began_steady + std::chrono::nanoseconds(d.nsecs)))
+ if(out_filename)
{
- return errc::timed_out;
+ out_filename->get() = filename.path();
}
+ return success(std::move(currentdirh));
}
- else
+ // Check timeout
+ if(d)
{
- if(std::chrono::system_clock::now() >= end_utc)
+ if(d.steady)
+ {
+ if(std::chrono::steady_clock::now() >= (began_steady + std::chrono::nanoseconds(d.nsecs)))
+ {
+ return errc::timed_out;
+ }
+ }
+ else
{
- return errc::timed_out;
+ if(std::chrono::system_clock::now() >= end_utc)
+ {
+ return errc::timed_out;
+ }
}
}
}
}
- }
- catch(...)
- {
- return error_from_exception();
+ catch(...)
+ {
+ return error_from_exception();
+ }
}
}
result<path_handle> fs_handle::parent_path_handle(deadline d) const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
auto &h = _get_handle();
if(_devid == 0 && _inode == 0)
{
OUTCOME_TRY(_fetch_inode());
}
- return containing_directory({}, h, *this, d);
+ return detail::containing_directory({}, h, *this, d);
}
result<void> fs_handle::relink(const path_handle &base, path_view_type path, bool atomic_replace, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
auto &h = const_cast<handle &>(_get_handle());
path_view::c_str zpath(path);
#ifdef O_TMPFILE
@@ -181,7 +173,7 @@ result<void> fs_handle::relink(const path_handle &base, path_view_type path, boo
{
OUTCOME_TRY(_fetch_inode());
}
- OUTCOME_TRY(dirh, containing_directory(std::ref(filename), h, *this, d));
+ OUTCOME_TRY(dirh, detail::containing_directory(std::ref(filename), h, *this, d));
if(!atomic_replace)
{
// Some systems provide an extension for atomic non-replacing renames
@@ -206,7 +198,7 @@ result<void> fs_handle::relink(const path_handle &base, path_view_type path, boo
result<void> fs_handle::unlink(deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
auto &h = _get_handle();
// Open our containing directory
filesystem::path filename;
@@ -214,7 +206,7 @@ result<void> fs_handle::unlink(deadline d) noexcept
{
OUTCOME_TRY(_fetch_inode());
}
- OUTCOME_TRY(dirh, containing_directory(std::ref(filename), h, *this, d));
+ OUTCOME_TRY(dirh, detail::containing_directory(std::ref(filename), h, *this, d));
if(-1 == ::unlinkat(dirh.native_handle().fd, filename.c_str(), h.is_directory() ? AT_REMOVEDIR : 0))
{
return posix_error();
@@ -222,4 +214,4 @@ result<void> fs_handle::unlink(deadline d) noexcept
return success();
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/handle.ipp b/include/llfio/v2.0/detail/impl/posix/handle.ipp
index c5143830..37884e0b 100644
--- a/include/afio/v2.0/detail/impl/posix/handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/handle.ipp
@@ -36,7 +36,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <sys/stat.h> // for struct stat
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
handle::~handle()
{
@@ -46,7 +46,7 @@ handle::~handle()
auto ret = handle::close();
if(ret.has_error())
{
- AFIO_LOG_FATAL(_v.fd, "handle::~handle() close failed");
+ LLFIO_LOG_FATAL(_v.fd, "handle::~handle() close failed");
abort();
}
}
@@ -54,7 +54,7 @@ handle::~handle()
result<handle::path_type> handle::current_path() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
try
{
// Most efficient, least memory copying method is direct fill of a string which is moved into filesystem::path
@@ -131,9 +131,17 @@ result<handle::path_type> handle::current_path() const noexcept
result<void> handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_v)
{
+#ifndef NDEBUG
+ // Trap when refined handle implementations don't set their vptr properly (this took a while to debug!)
+ if((static_cast<unsigned>(_v.behaviour) & 0xff00) != 0 && !(_v.behaviour & native_handle_type::disposition::_child_close_executed))
+ {
+ LLFIO_LOG_FATAL(this, "handle::close() called on a derived handle implementation, this suggests vptr is incorrect");
+ abort();
+ }
+#endif
if(are_safety_fsyncs_issued() && is_writable())
{
if(-1 == fsync(_v.fd))
@@ -152,20 +160,41 @@ result<void> handle::close() noexcept
result<handle> handle::clone() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
result<handle> ret(handle(native_handle_type(), _caching, _flags));
ret.value()._v.behaviour = _v.behaviour;
- ret.value()._v.fd = ::fcntl(_v.fd, F_DUPFD_CLOEXEC);
+ ret.value()._v.fd = ::fcntl(_v.fd, F_DUPFD_CLOEXEC, 0);
if(-1 == ret.value()._v.fd)
{
- return posix_error();
+ int e = errno;
+ if(e == EBADF)
+ {
+ // Fall back onto F_DUPFD
+ ret.value()._v.fd = ::fcntl(_v.fd, F_DUPFD, 0);
+ if(-1 != ret.value()._v.fd)
+ {
+ // Set close on exec
+ int attribs = ::fcntl(_v.fd, F_GETFL);
+ if(-1 == attribs)
+ {
+ return posix_error();
+ }
+ attribs |= FD_CLOEXEC;
+ if(-1 == ::fcntl(_v.fd, F_SETFL, attribs))
+ {
+ return posix_error();
+ }
+ return ret;
+ }
+ }
+ return posix_error(e);
}
return ret;
}
result<void> handle::set_append_only(bool enable) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
int attribs = ::fcntl(_v.fd, F_GETFL);
if(-1 == attribs)
{
@@ -194,4 +223,4 @@ result<void> handle::set_append_only(bool enable) noexcept
return success();
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/import.hpp b/include/llfio/v2.0/detail/impl/posix/import.hpp
index 64f4bd2b..17770daa 100644
--- a/include/afio/v2.0/detail/impl/posix/import.hpp
+++ b/include/llfio/v2.0/detail/impl/posix/import.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_POSIX_HPP
-#define AFIO_POSIX_HPP
+#ifndef LLFIO_POSIX_HPP
+#define LLFIO_POSIX_HPP
#include "../../../handle.hpp"
@@ -34,7 +34,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <fcntl.h>
#include <unistd.h>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
inline result<int> attribs_from_handle_mode_caching_and_flags(native_handle_type &nativeh, handle::mode _mode, handle::creation _creation, handle::caching _caching, handle::flag /*unused*/) noexcept
{
@@ -111,6 +111,6 @@ inline result<int> attribs_from_handle_mode_caching_and_flags(native_handle_type
return attribs;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/detail/impl/posix/io_handle.ipp b/include/llfio/v2.0/detail/impl/posix/io_handle.ipp
index c33ec08a..d2e5b82a 100644
--- a/include/afio/v2.0/detail/impl/posix/io_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/io_handle.ipp
@@ -28,11 +28,18 @@ Distributed under the Boost Software License, Version 1.0.
#include <fcntl.h>
#include <sys/uio.h> // for preadv etc
#include <unistd.h>
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
#include <aio.h>
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
+
+constexpr inline void _check_iovec_match()
+{
+ static_assert(sizeof(io_handle::buffer_type) == sizeof(iovec), "buffer_type and struct iovec do not match in size");
+ static_assert(offsetof(io_handle::buffer_type, _data) == offsetof(iovec, iov_base), "buffer_type and struct iovec do not have same offset of data member");
+ static_assert(offsetof(io_handle::buffer_type, _len) == offsetof(iovec, iov_len), "buffer_type and struct iovec do not have same offset of len member");
+}
size_t io_handle::max_buffers() const noexcept
{
@@ -59,7 +66,7 @@ size_t io_handle::max_buffers() const noexcept
io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_request<io_handle::buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(d)
{
return errc::not_supported;
@@ -76,7 +83,6 @@ io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_requ
iov[n].iov_len = reqs.buffers[n].len;
}
#else
- static_assert(sizeof(buffer_type) == sizeof(iovec), "buffer_type and struct iovec do not match");
auto *iov = reinterpret_cast<struct iovec *>(reqs.buffers.data());
#endif
#ifndef NDEBUG
@@ -91,7 +97,7 @@ io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_requ
}
#endif
ssize_t bytesread = 0;
-#if AFIO_MISSING_PIOV
+#if LLFIO_MISSING_PIOV
off_t offset = reqs.offset;
for(size_t n = 0; n < reqs.buffers.size(); n++)
{
@@ -107,18 +113,18 @@ io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_requ
}
for(auto &buffer : reqs.buffers)
{
- if(buffer.len >= static_cast<size_t>(bytesread))
+ if(buffer.size() >= static_cast<size_t>(bytesread))
{
- bytesread -= buffer.len;
+ bytesread -= buffer.size();
}
else if(bytesread > 0)
{
- buffer.len = bytesread;
+ buffer = {buffer.data(), (size_type) bytesread};
bytesread = 0;
}
else
{
- buffer.len = 0;
+ buffer = {buffer.data(), 0};
}
}
return {reqs.buffers};
@@ -126,7 +132,7 @@ io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_requ
io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::io_request<io_handle::const_buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(d)
{
return errc::not_supported;
@@ -143,7 +149,6 @@ io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::
iov[n].iov_len = reqs.buffers[n].len;
}
#else
- static_assert(sizeof(buffer_type) == sizeof(iovec), "buffer_type and struct iovec do not match");
auto *iov = reinterpret_cast<struct iovec *>(reqs.buffers.data());
#endif
#ifndef NDEBUG
@@ -158,7 +163,7 @@ io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::
}
#endif
ssize_t byteswritten = 0;
-#if AFIO_MISSING_PIOV
+#if LLFIO_MISSING_PIOV
off_t offset = reqs.offset;
for(size_t n = 0; n < reqs.buffers.size(); n++)
{
@@ -174,18 +179,18 @@ io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::
}
for(auto &buffer : reqs.buffers)
{
- if(buffer.len >= static_cast<size_t>(byteswritten))
+ if(buffer.size() >= static_cast<size_t>(byteswritten))
{
- byteswritten -= buffer.len;
+ byteswritten -= buffer.size();
}
else if(byteswritten > 0)
{
- buffer.len = byteswritten;
+ buffer = {buffer.data(), (size_type) byteswritten};
byteswritten = 0;
}
else
{
- buffer.len = 0;
+ buffer = {buffer.data(), 0};
}
}
return {reqs.buffers};
@@ -193,7 +198,7 @@ io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::
result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, io_handle::extent_type bytes, bool exclusive, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(d && d.nsecs > 0)
{
return errc::not_supported;
@@ -218,11 +223,11 @@ result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, i
constexpr extent_type extent_topbit = static_cast<extent_type>(1) << (8 * sizeof(extent_type) - 1);
if((offset & extent_topbit) != 0u)
{
- AFIO_LOG_WARN(_v.fd, "io_handle::lock() called with offset with top bit set, masking out");
+ LLFIO_LOG_WARN(_v.fd, "io_handle::lock() called with offset with top bit set, masking out");
}
if((bytes & extent_topbit) != 0u)
{
- AFIO_LOG_WARN(_v.fd, "io_handle::lock() called with bytes with top bit set, masking out");
+ LLFIO_LOG_WARN(_v.fd, "io_handle::lock() called with bytes with top bit set, masking out");
}
fl.l_whence = SEEK_SET;
fl.l_start = offset & ~extent_topbit;
@@ -257,8 +262,6 @@ result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, i
{
return errc::timed_out;
}
-
-
return posix_error();
}
return extent_guard(this, offset, bytes, exclusive);
@@ -266,7 +269,7 @@ result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, i
void io_handle::unlock(io_handle::extent_type offset, io_handle::extent_type bytes) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
bool failed = false;
#if !defined(__linux__) && !defined(F_OFD_SETLK)
if(0 == bytes)
@@ -308,10 +311,10 @@ void io_handle::unlock(io_handle::extent_type offset, io_handle::extent_type byt
{
auto ret(posix_error());
(void) ret;
- AFIO_LOG_FATAL(_v.fd, "io_handle::unlock() failed");
+ LLFIO_LOG_FATAL(_v.fd, "io_handle::unlock() failed");
std::terminate();
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/io_service.ipp b/include/llfio/v2.0/detail/impl/posix/io_service.ipp
index 72560b40..c68f40c4 100644
--- a/include/afio/v2.0/detail/impl/posix/io_service.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/io_service.ipp
@@ -25,17 +25,17 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../async_file_handle.hpp"
#include <pthread.h>
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
#include <aio.h>
#include <sys/mman.h>
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_COMPILE_KQUEUES
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
static int interrupt_signal;
static struct sigaction interrupt_signal_handler_old_action;
@@ -63,7 +63,7 @@ int io_service::set_interruption_signal(int signo)
}
if(signo != 0)
{
-#if AFIO_HAVE_REALTIME_SIGNALS
+#if LLFIO_HAVE_REALTIME_SIGNALS
if(-1 == signo)
{
for(signo = SIGRTMIN; signo < SIGRTMAX; signo++)
@@ -136,10 +136,10 @@ io_service::io_service()
: _work_queued(0)
{
_threadh = pthread_self();
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
_use_kqueues = true;
_blocked_interrupt_signal = 0;
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_COMPILE_KQUEUES
_kqueueh = 0;
#error todo
#else
@@ -162,8 +162,8 @@ io_service::~io_service()
std::this_thread::yield();
}
}
-#if AFIO_USE_POSIX_AIO
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_USE_POSIX_AIO
+#if LLFIO_COMPILE_KQUEUES
if(_kqueueh)
::close(_kqueueh);
#endif
@@ -177,7 +177,7 @@ io_service::~io_service()
#endif
}
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
void io_service::disable_kqueues()
{
if(_use_kqueues)
@@ -277,11 +277,11 @@ result<bool> io_service::run_until(deadline d) noexcept
return _work_queued != 0;
}
}
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
int errcode = 0;
if(_use_kqueues)
{
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_COMPILE_KQUEUES
#error todo
#endif
}
@@ -381,10 +381,10 @@ void io_service::_post(detail::function_ptr<void(io_service *)> &&f)
_posts.push_back(std::move(pi));
}
_work_enqueued();
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
if(_use_kqueues)
{
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_COMPILE_KQUEUES
#error todo
#endif
}
@@ -394,7 +394,7 @@ void io_service::_post(detail::function_ptr<void(io_service *)> &&f)
// of the aio_suspend(), we need to pump this until run_until() notices
while(_need_signal)
{
- //# if AFIO_HAVE_REALTIME_SIGNALS
+ //# if LLFIO_HAVE_REALTIME_SIGNALS
// sigval val = { 0 };
// pthread_sigqueue(_threadh, interrupt_signal, val);
//#else
@@ -407,4 +407,4 @@ void io_service::_post(detail::function_ptr<void(io_service *)> &&f)
#endif
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/map_handle.ipp b/include/llfio/v2.0/detail/impl/posix/map_handle.ipp
index 0c4944d1..1c174f03 100644
--- a/include/afio/v2.0/detail/impl/posix/map_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/map_handle.ipp
@@ -37,7 +37,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <sys/mman.h>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
section_handle::~section_handle()
{
@@ -46,14 +46,14 @@ section_handle::~section_handle()
auto ret = section_handle::close();
if(ret.has_error())
{
- AFIO_LOG_FATAL(_v.h, "section_handle::~section_handle() close failed");
+ LLFIO_LOG_FATAL(_v.h, "section_handle::~section_handle() close failed");
abort();
}
}
}
result<void> section_handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_v)
{
// We don't want ~handle() to close our handle borrowed from the backing file or _anonymous
@@ -79,7 +79,7 @@ result<section_handle> section_handle::section(file_handle &backing, extent_type
nativeh.behaviour |= native_handle_type::disposition::writable;
}
nativeh.behaviour |= native_handle_type::disposition::section;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
return ret;
}
@@ -100,13 +100,13 @@ result<section_handle> section_handle::section(extent_type bytes, const path_han
nativeh.behaviour |= native_handle_type::disposition::writable;
}
nativeh.behaviour |= native_handle_type::disposition::section;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
return ret;
}
result<section_handle::extent_type> section_handle::length() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
struct stat s
{
};
@@ -120,7 +120,7 @@ result<section_handle::extent_type> section_handle::length() const noexcept
result<section_handle::extent_type> section_handle::truncate(extent_type newsize) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if((_backing == nullptr) && newsize > 0)
{
if(-1 == ::ftruncate(_anonymous.native_handle().fd, newsize))
@@ -143,7 +143,7 @@ map_handle::~map_handle()
auto ret = map_handle::close();
if(ret.has_error())
{
- AFIO_LOG_FATAL(_v.fd, "map_handle::~map_handle() close failed");
+ LLFIO_LOG_FATAL(_v.fd, "map_handle::~map_handle() close failed");
abort();
}
}
@@ -151,7 +151,7 @@ map_handle::~map_handle()
result<void> map_handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_addr != nullptr)
{
if(is_writable() && (_flag & section_handle::flag::barrier_on_close))
@@ -173,7 +173,7 @@ result<void> map_handle::close() noexcept
native_handle_type map_handle::release() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// We don't want ~handle() to close our borrowed handle
_v = native_handle_type();
_addr = nullptr;
@@ -183,17 +183,17 @@ native_handle_type map_handle::release() noexcept
map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_handle::io_request<map_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
extent_type bytes = 0;
// Check for overflow
for(const auto &req : reqs.buffers)
{
- if(bytes + req.len < bytes)
+ if(bytes + req.size() < bytes)
{
return errc::value_too_large;
}
- bytes += req.len;
+ bytes += req.size();
}
// If empty, do the whole file
if(reqs.buffers.empty())
@@ -204,7 +204,7 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_ha
if(!and_metadata && is_nvram())
{
auto synced = barrier({addr, bytes});
- if(synced.len >= bytes)
+ if(synced.size() >= bytes)
{
return {reqs.buffers};
}
@@ -305,8 +305,9 @@ static inline result<void *> do_mmap(native_handle_type &nativeh, void *ataddr,
return addr;
}
-result<map_handle> map_handle::map(size_type bytes, section_handle::flag _flag) noexcept
+result<map_handle> map_handle::map(size_type bytes, bool /*unused*/, section_handle::flag _flag) noexcept
{
+ // TODO: Keep a cache of MADV_FREE pages deallocated
if(bytes == 0u)
{
return errc::argument_out_of_domain;
@@ -318,7 +319,7 @@ result<map_handle> map_handle::map(size_type bytes, section_handle::flag _flag)
ret.value()._addr = static_cast<byte *>(addr);
ret.value()._reservation = bytes;
ret.value()._length = bytes;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
return ret;
}
@@ -338,13 +339,13 @@ result<map_handle> map_handle::map(section_handle &section, size_type bytes, ext
ret.value()._length = (length - offset < bytes) ? (length - offset) : bytes; // length of backing, not reservation
// Make my handle borrow the native handle of my backing storage
ret.value()._v.fd = section.native_handle().fd;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
return ret;
}
result<map_handle::size_type> map_handle::truncate(size_type newsize, bool permit_relocation) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
extent_type length = _length;
if(_section != nullptr)
{
@@ -425,18 +426,18 @@ result<map_handle::size_type> map_handle::truncate(size_type newsize, bool permi
result<map_handle::buffer_type> map_handle::commit(buffer_type region, section_handle::flag flag) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- if(region.data == nullptr)
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
// Set permissions on the pages
region = utils::round_to_page_size(region);
- extent_type offset = _offset + (region.data - _addr);
- size_type bytes = region.len;
- OUTCOME_TRYV(do_mmap(_v, region.data, MAP_FIXED, _section, bytes, offset, flag));
+ extent_type offset = _offset + (region.data() - _addr);
+ size_type bytes = region.size();
+ OUTCOME_TRYV(do_mmap(_v, region.data(), MAP_FIXED, _section, bytes, offset, flag));
// Tell the kernel we will be using these pages soon
- if(-1 == ::madvise(region.data, region.len, MADV_WILLNEED))
+ if(-1 == ::madvise(region.data(), region.size(), MADV_WILLNEED))
{
return posix_error();
}
@@ -445,52 +446,52 @@ result<map_handle::buffer_type> map_handle::commit(buffer_type region, section_h
result<map_handle::buffer_type> map_handle::decommit(buffer_type region) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- if(region.data == nullptr)
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
region = utils::round_to_page_size(region);
// Tell the kernel to kick these pages into storage
- if(-1 == ::madvise(region.data, region.len, MADV_DONTNEED))
+ if(-1 == ::madvise(region.data(), region.size(), MADV_DONTNEED))
{
return posix_error();
}
// Set permissions on the pages to no access
- extent_type offset = _offset + (region.data - _addr);
- size_type bytes = region.len;
- OUTCOME_TRYV(do_mmap(_v, region.data, MAP_FIXED, _section, bytes, offset, section_handle::flag::none));
+ extent_type offset = _offset + (region.data() - _addr);
+ size_type bytes = region.size();
+ OUTCOME_TRYV(do_mmap(_v, region.data(), MAP_FIXED, _section, bytes, offset, section_handle::flag::none));
return region;
}
result<void> map_handle::zero_memory(buffer_type region) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- if(region.data == nullptr)
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
#ifdef MADV_REMOVE
- buffer_type page_region{utils::round_up_to_page_size(region.data), utils::round_down_to_page_size(region.len)};
+ buffer_type page_region{utils::round_up_to_page_size(region.data()), utils::round_down_to_page_size(region.size())};
// Zero contents and punch a hole in any backing storage
- if((page_region.len != 0u) && -1 != ::madvise(page_region.data, page_region.len, MADV_REMOVE))
+ if((page_region.size() != 0u) && -1 != ::madvise(page_region.data(), page_region.size(), MADV_REMOVE))
{
- memset(region.data, 0, page_region.data - region.data);
- memset(page_region.data + page_region.len, 0, (region.data + region.len) - (page_region.data + page_region.len));
+ memset(region.data(), 0, page_region.data() - region.data());
+ memset(page_region.data() + page_region.size(), 0, (region.data() + region.size()) - (page_region.data() + page_region.size()));
return success();
}
#endif
//! Only Linux implements syscall zero(), and it's covered by MADV_REMOVE already
- memset(region.data, 0, region.len);
+ memset(region.data(), 0, region.size());
return success();
}
result<span<map_handle::buffer_type>> map_handle::prefetch(span<buffer_type> regions) noexcept
{
- AFIO_LOG_FUNCTION_CALL(0);
- for(const auto &region : regions)
+ LLFIO_LOG_FUNCTION_CALL(0);
+ for(auto &region : regions)
{
- if(-1 == ::madvise(region.data, region.len, MADV_WILLNEED))
+ if(-1 == ::madvise(region.data(), region.size(), MADV_WILLNEED))
{
return posix_error();
}
@@ -500,50 +501,50 @@ result<span<map_handle::buffer_type>> map_handle::prefetch(span<buffer_type> reg
result<map_handle::buffer_type> map_handle::do_not_store(buffer_type region) noexcept
{
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
region = utils::round_to_page_size(region);
- if(region.data == nullptr)
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
#ifdef MADV_FREE
// Lightweight unset of dirty bit for these pages. Needs FreeBSD or very recent Linux.
- if(-1 != ::madvise(region.data, region.len, MADV_FREE))
+ if(-1 != ::madvise(region.data(), region.size(), MADV_FREE))
return region;
#endif
#ifdef MADV_REMOVE
// This is rather heavy weight in that it also punches a hole in any backing storage
// but it works on Linux for donkey's years
- if(-1 != ::madvise(region.data, region.len, MADV_REMOVE))
+ if(-1 != ::madvise(region.data(), region.size(), MADV_REMOVE))
{
return region;
}
#endif
// No support on this platform
- region.len = 0;
+ region = {region.data(), 0};
return region;
}
map_handle::io_result<map_handle::buffers_type> map_handle::read(io_request<buffers_type> reqs, deadline /*d*/) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
for(buffer_type &req : reqs.buffers)
{
if(togo != 0u)
{
- req.data = addr;
- if(req.len > togo)
+ req = {addr, req.size()};
+ if(req.size() > togo)
{
- req.len = togo;
+ req = {req.data(), togo};
}
- addr += req.len;
- togo -= req.len;
+ addr += req.size();
+ togo -= req.size();
}
else
{
- req.len = 0;
+ req = {req.data(), 0};
}
}
return reqs.buffers;
@@ -551,7 +552,7 @@ map_handle::io_result<map_handle::buffers_type> map_handle::read(io_request<buff
map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_request<const_buffers_type> reqs, deadline /*d*/) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
if(QUICKCPPLIB_NAMESPACE::signal_guard::signal_guard(QUICKCPPLIB_NAMESPACE::signal_guard::signalc::undefined_memory_access,
@@ -560,18 +561,18 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_reque
{
if(togo != 0u)
{
- if(req.len > togo)
+ if(req.size() > togo)
{
- req.len = togo;
+ req = {req.data(), togo};
}
- memcpy(addr, req.data, req.len);
- req.data = addr;
- addr += req.len;
- togo -= req.len;
+ memcpy(addr, req.data(), req.size());
+ req = {addr, req.size()};
+ addr += req.size();
+ togo -= req.size();
}
else
{
- req.len = 0;
+ req = {req.data(), 0};
}
}
return false;
@@ -593,4 +594,4 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_reque
return reqs.buffers;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp b/include/llfio/v2.0/detail/impl/posix/mapped_file_handle.ipp
index 484bbdd2..10ff177d 100644
--- a/include/afio/v2.0/detail/impl/posix/mapped_file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/mapped_file_handle.ipp
@@ -25,11 +25,11 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../mapped_file_handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<mapped_file_handle::size_type> mapped_file_handle::reserve(size_type reservation) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
OUTCOME_TRY(length, underlying_file_maximum_extent());
if(length == 0)
{
@@ -66,7 +66,7 @@ result<mapped_file_handle::size_type> mapped_file_handle::reserve(size_type rese
result<void> mapped_file_handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_mh.is_valid())
{
OUTCOME_TRYV(_mh.close());
@@ -79,7 +79,7 @@ result<void> mapped_file_handle::close() noexcept
}
native_handle_type mapped_file_handle::release() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_mh.is_valid())
{
(void) _mh.close();
@@ -93,7 +93,7 @@ native_handle_type mapped_file_handle::release() noexcept
result<mapped_file_handle::extent_type> mapped_file_handle::truncate(extent_type newsize) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// Release all maps and sections and truncate the backing file to zero
if(newsize == 0)
{
@@ -159,4 +159,4 @@ result<mapped_file_handle::extent_type> mapped_file_handle::update_map() noexcep
return length;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/path_discovery.ipp b/include/llfio/v2.0/detail/impl/posix/path_discovery.ipp
index 0d072a29..675c8465 100644
--- a/include/afio/v2.0/detail/impl/posix/path_discovery.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/path_discovery.ipp
@@ -22,15 +22,15 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_PATH_DISCOVERY_INCLUDING
+#ifndef LLFIO_PATH_DISCOVERY_INCLUDING
#error Must be included by ../path_discovery.ipp only
#endif
-#include "../../../algorithm/mapped_span.hpp"
+#include "../../../map_view.hpp"
#include <pwd.h>
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace path_discovery
{
@@ -73,11 +73,11 @@ namespace path_discovery
{
std::string msg("path_discovery::all_temporary_directories() failed to open /etc/passwd due to ");
msg.append(_passwdh.error().message().c_str());
- AFIO_LOG_WARN(nullptr, msg.c_str());
+ LLFIO_LOG_WARN(nullptr, msg.c_str());
}
else
{
- algorithm::mapped_span<const char> passwd(_passwdh.value());
+ map_view<const char> passwd(_passwdh.value());
/* This will consist of lines of the form:
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8910,(234)555-0044,email:/home/jsmith:/bin/sh
@@ -142,4 +142,4 @@ namespace path_discovery
}
} // namespace path_discovery
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/path_handle.ipp b/include/llfio/v2.0/detail/impl/posix/path_handle.ipp
index 80a780e0..1c48d65e 100644
--- a/include/afio/v2.0/detail/impl/posix/path_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/path_handle.ipp
@@ -26,13 +26,13 @@ Distributed under the Boost Software License, Version 1.0.
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<path_handle> path_handle::path(const path_handle &base, path_handle::path_view_type path) noexcept
{
result<path_handle> ret{path_handle(native_handle_type())};
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::directory;
int attribs = O_CLOEXEC | O_RDONLY;
#ifdef O_DIRECTORY
@@ -58,4 +58,4 @@ result<path_handle> path_handle::path(const path_handle &base, path_handle::path
return ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/stat.ipp b/include/llfio/v2.0/detail/impl/posix/stat.ipp
index 07b6c310..28eb3ccb 100644
--- a/include/afio/v2.0/detail/impl/posix/stat.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/stat.ipp
@@ -27,7 +27,12 @@ Distributed under the Boost Software License, Version 1.0.
#include <sys/stat.h>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
+
+namespace detail
+{
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<void> stat_from_symlink(struct stat &s, const handle &h) noexcept;
+}
static inline filesystem::file_type to_st_type(uint16_t mode)
{
@@ -63,9 +68,9 @@ static inline std::chrono::system_clock::time_point to_timepoint(struct timespec
return std::chrono::system_clock::time_point(duration);
}
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat_t::want wanted) noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat_t::want wanted) noexcept
{
- AFIO_LOG_FUNCTION_CALL(&h);
+ LLFIO_LOG_FUNCTION_CALL(&h);
struct stat s
{
};
@@ -74,7 +79,12 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat
if(-1 == ::fstat(h.native_handle().fd, &s))
{
- return posix_error();
+ if(!h.is_symlink() || EBADF != errno)
+ {
+ return posix_error();
+ }
+ // This is a hack, but symlink_handle includes this first so there is a chicken and egg dependency problem
+ OUTCOME_TRY(detail::stat_from_symlink(s, h));
}
if(wanted & want::dev)
{
@@ -222,4 +232,4 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat
return ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/statfs.ipp b/include/llfio/v2.0/detail/impl/posix/statfs.ipp
index 2f94ab8e..82591ea5 100644
--- a/include/afio/v2.0/detail/impl/posix/statfs.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/statfs.ipp
@@ -31,9 +31,9 @@ Distributed under the Boost Software License, Version 1.0.
#include <sys/statfs.h>
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, statfs_t::want wanted) noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, statfs_t::want wanted) noexcept
{
size_t ret = 0;
#ifdef __linux__
@@ -141,7 +141,7 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, st
}
}
}
-#ifndef AFIO_COMPILING_FOR_GCOV
+#ifndef LLFIO_COMPILING_FOR_GCOV
if(mountentries.empty())
{
return errc::no_such_file_or_directory;
@@ -297,4 +297,4 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, st
return ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/storage_profile.ipp b/include/llfio/v2.0/detail/impl/posix/storage_profile.ipp
index a92e0470..b6f151f2 100644
--- a/include/afio/v2.0/detail/impl/posix/storage_profile.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/storage_profile.ipp
@@ -35,7 +35,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <sys/sysctl.h>
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace storage_profile
{
@@ -322,4 +322,4 @@ namespace storage_profile
} // namespace storage
} // namespace storage_profile
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/llfio/v2.0/detail/impl/posix/symlink_handle.ipp b/include/llfio/v2.0/detail/impl/posix/symlink_handle.ipp
new file mode 100644
index 00000000..2233ec33
--- /dev/null
+++ b/include/llfio/v2.0/detail/impl/posix/symlink_handle.ipp
@@ -0,0 +1,468 @@
+/* A handle to a symbolic link
+(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
+File Created: Jul 2018
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "../../../symlink_handle.hpp"
+#include "import.hpp"
+
+LLFIO_V2_NAMESPACE_BEGIN
+
+namespace detail
+{
+ // Used by stat_t.cpp to work around a dependency problem
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<void> stat_from_symlink(struct stat &s, const handle &_h) noexcept
+ {
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ (void) s;
+ (void) _h;
+ return posix_error(EBADF);
+#else
+ const auto &h = static_cast<const symlink_handle &>(_h);
+ if(-1 == ::fstatat(h._dirh.native_handle().fd, h._leafname.c_str(), &s, AT_SYMLINK_NOFOLLOW))
+ {
+ return posix_error();
+ }
+ return success();
+#endif
+ }
+}
+
+result<void> symlink_handle::_create_symlink(const path_handle &dirh, const handle::path_type &filename, path_view target, deadline d, bool atomic_replace) noexcept
+{
+ std::chrono::steady_clock::time_point began_steady;
+ std::chrono::system_clock::time_point end_utc;
+ if(d)
+ {
+ if(d.steady)
+ {
+ began_steady = std::chrono::steady_clock::now();
+ }
+ else
+ {
+ end_utc = d.to_time_point();
+ }
+ }
+ path_view::c_str zpath(target);
+ try
+ {
+ if(atomic_replace)
+ {
+ // symlinkat() won't replace an existing symlink, so we need to create it
+ // with a random name and atomically rename over the existing one.
+ for(;;)
+ {
+ auto randomname = utils::random_string(32);
+ randomname.append(".random");
+ // std::cerr << "symlinkat " << zpath.buffer << " " << dirh.native_handle().fd << " " << randomname << std::endl;
+ if(-1 == ::symlinkat(zpath.buffer, dirh.is_valid() ? dirh.native_handle().fd : AT_FDCWD, randomname.c_str()))
+ {
+ if(EEXIST == errno)
+ {
+ // Check timeout
+ if(d)
+ {
+ if(d.steady)
+ {
+ if(std::chrono::steady_clock::now() >= (began_steady + std::chrono::nanoseconds(d.nsecs)))
+ {
+ return errc::timed_out;
+ }
+ }
+ else
+ {
+ if(std::chrono::system_clock::now() >= end_utc)
+ {
+ return errc::timed_out;
+ }
+ }
+ }
+ continue;
+ }
+ return posix_error();
+ }
+ // std::cerr << "renameat " << dirh.native_handle().fd << " " << randomname << " " << filename << std::endl;
+ if(-1 == ::renameat(dirh.is_valid() ? dirh.native_handle().fd : AT_FDCWD, randomname.c_str(), dirh.is_valid() ? dirh.native_handle().fd : AT_FDCWD, filename.c_str()))
+ {
+ return posix_error();
+ }
+ return success();
+ }
+ }
+ else
+ {
+ // std::cerr << "symlinkat " << zpath.buffer << " " << dirh.native_handle().fd << " " << filename << std::endl;
+ if(-1 == ::symlinkat(zpath.buffer, dirh.is_valid() ? dirh.native_handle().fd : AT_FDCWD, filename.c_str()))
+ {
+ return posix_error();
+ }
+ return success();
+ }
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+}
+
+result<symlink_handle> symlink_handle::clone(mode mode_, deadline d) const noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+#if LLFIO_SYMLINK_HANDLE_IS_FAKED
+ result<symlink_handle> ret(symlink_handle(native_handle_type(), _devid, _inode, _flags));
+ ret.value()._v.behaviour = _v.behaviour;
+ OUTCOME_TRY(dirh, _dirh.clone());
+ ret.value()._dirh = std::move(dirh);
+ try
+ {
+ ret.value()._leafname = _leafname;
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+ return ret;
+#endif
+ // fast path
+ if(mode_ == mode::unchanged)
+ {
+ result<symlink_handle> ret(symlink_handle(native_handle_type(), _devid, _inode, _flags));
+ ret.value()._v.behaviour = _v.behaviour;
+ ret.value()._v.fd = ::fcntl(_v.fd, F_DUPFD_CLOEXEC);
+ if(-1 == ret.value()._v.fd)
+ {
+ return posix_error();
+ }
+ return ret;
+ }
+ // Slow path
+ std::chrono::steady_clock::time_point began_steady;
+ std::chrono::system_clock::time_point end_utc;
+ if(d)
+ {
+ if(d.steady)
+ {
+ began_steady = std::chrono::steady_clock::now();
+ }
+ else
+ {
+ end_utc = d.to_time_point();
+ }
+ }
+ for(;;)
+ {
+ // Get the current path of myself
+ OUTCOME_TRY(currentpath, current_path());
+ // Open myself
+ auto fh = symlink({}, currentpath, mode_, creation::open_existing, _flags);
+ if(fh)
+ {
+ if(fh.value().unique_id() == unique_id())
+ {
+ return fh;
+ }
+ }
+ else
+ {
+ if(fh.error() != errc::no_such_file_or_directory)
+ {
+ return fh.error();
+ }
+ }
+ // Check timeout
+ if(d)
+ {
+ if(d.steady)
+ {
+ if(std::chrono::steady_clock::now() >= (began_steady + std::chrono::nanoseconds(d.nsecs)))
+ {
+ return errc::timed_out;
+ }
+ }
+ else
+ {
+ if(std::chrono::system_clock::now() >= end_utc)
+ {
+ return errc::timed_out;
+ }
+ }
+ }
+ }
+}
+
+#if LLFIO_SYMLINK_HANDLE_IS_FAKED
+result<symlink_handle::path_type> symlink_handle::current_path() const noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+ try
+ {
+ // Deleted?
+ if(!_dirh.is_valid() && _leafname.empty())
+ {
+ return _leafname;
+ }
+ for(;;)
+ {
+ // Sanity check that we still exist
+ struct stat s1, s2;
+ if(-1 == ::fstatat(_dirh.native_handle().fd, _leafname.c_str(), &s1, AT_SYMLINK_NOFOLLOW))
+ {
+ return posix_error();
+ }
+ OUTCOME_TRY(dirpath, _dirh.current_path());
+ dirpath /= _leafname;
+ if(-1 == ::lstat(dirpath.c_str(), &s2) || s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino)
+ {
+ continue;
+ }
+ return dirpath;
+ }
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+}
+
+result<void> symlink_handle::relink(const path_handle &base, path_view_type path, bool atomic_replace, deadline d) noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+ OUTCOME_TRY(fs_handle::relink(base, path, atomic_replace, d));
+ try
+ {
+ // Take a path handle to the directory containing the symlink
+ auto path_parent = path.parent_path();
+ _leafname = path.filename().path();
+ if(base.is_valid() && path_parent.empty())
+ {
+ OUTCOME_TRY(dh, base.clone());
+ _dirh = std::move(dh);
+ }
+ else if(!path_parent.empty())
+ {
+ OUTCOME_TRY(dh, path_handle::path(base, path_parent));
+ _dirh = std::move(dh);
+ }
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+ return success();
+}
+
+result<void> symlink_handle::unlink(deadline d) noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+ OUTCOME_TRY(fs_handle::unlink(d));
+ _dirh = {};
+ _leafname = path_type();
+ return success();
+}
+#endif
+
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<symlink_handle> symlink_handle::symlink(const path_handle &base, symlink_handle::path_view_type path, symlink_handle::mode _mode, symlink_handle::creation _creation, flag flags) noexcept
+{
+ result<symlink_handle> ret(symlink_handle(native_handle_type(), 0, 0, flags));
+ native_handle_type &nativeh = ret.value()._v;
+ LLFIO_LOG_FUNCTION_CALL(&ret);
+ nativeh.behaviour |= native_handle_type::disposition::symlink;
+ if(_mode == mode::append || _creation == creation::truncate)
+ {
+ return errc::function_not_supported;
+ }
+ OUTCOME_TRY(attribs, attribs_from_handle_mode_caching_and_flags(nativeh, _mode, _creation, caching::all, flags));
+ nativeh.behaviour &= ~native_handle_type::disposition::seekable; // not seekable
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ path_handle dirh;
+ path_type leafname;
+#else
+ (void) attribs;
+ path_handle &dirh = ret.value()._dirh;
+ path_type &leafname = ret.value()._leafname;
+#endif
+ int dirhfd = AT_FDCWD;
+ try
+ {
+ // Take a path handle to the directory containing the symlink
+ auto path_parent = path.parent_path();
+ leafname = path.filename().path();
+ if(base.is_valid() && path_parent.empty())
+ {
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ dirhfd = base.native_handle().fd;
+#else
+ OUTCOME_TRY(dh, base.clone());
+ dirh = std::move(dh);
+ dirhfd = dirh.native_handle().fd;
+#endif
+ }
+ else
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED // always take a dirh if faking the handle for race safety
+ if(!path_parent.empty())
+#endif
+ {
+ OUTCOME_TRY(dh, path_handle::path(base, path_parent.empty() ? "." : path_parent));
+ dirh = std::move(dh);
+ dirhfd = dirh.native_handle().fd;
+ }
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+ switch(_creation)
+ {
+ case creation::open_existing:
+ {
+ // Complain if it doesn't exist
+ struct stat s;
+ if(-1 == ::fstatat(dirhfd, leafname.c_str(), &s, AT_SYMLINK_NOFOLLOW))
+ {
+ return posix_error();
+ }
+ break;
+ }
+ case creation::only_if_not_exist:
+ case creation::if_needed:
+ case creation::truncate:
+ {
+ // Create an empty symlink, ignoring any file exists errors, unless only_if_not_exist
+ auto r = ret.value()._create_symlink(dirh, leafname,
+#ifdef __linux__
+ ".", // Linux is not POSIX conforming here, and refuses to create empty symlinks
+#else
+ "",
+#endif
+ std::chrono::seconds(10), false);
+ if(!r)
+ {
+ if(_creation == creation::only_if_not_exist || r.error() != errc::file_exists)
+ return r.error();
+ }
+ break;
+ }
+ }
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ // Linux can open symbolic links directly like this
+ attribs |= O_PATH | O_NOFOLLOW;
+ nativeh.fd = ::openat(dirhfd, leafname.c_str(), attribs, 0x1b0 /*660*/);
+ if(-1 == nativeh.fd)
+ {
+ return posix_error();
+ }
+#endif
+ return ret;
+}
+
+result<symlink_handle::buffers_type> symlink_handle::read(symlink_handle::io_request<symlink_handle::buffers_type> req) noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+ symlink_handle::buffers_type tofill;
+ if(req.kernelbuffer.empty())
+ {
+ // Let's assume the average symbolic link will be 256 characters long.
+ size_t toallocate = 256;
+ auto *mem = new(std::nothrow) char[toallocate];
+ if(mem == nullptr)
+ {
+ return errc::not_enough_memory;
+ }
+ tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
+ tofill._kernel_buffer_size = toallocate;
+ }
+ for(;;)
+ {
+ char *buffer = req.kernelbuffer.empty() ? tofill._kernel_buffer.get() : req.kernelbuffer.data();
+ size_t bytes = req.kernelbuffer.empty() ? tofill._kernel_buffer_size : req.kernelbuffer.size();
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ // Linux has the ability to read the link from a fd
+ ssize_t read = ::readlinkat(_v.fd, "", buffer, bytes);
+#else
+ ssize_t read = ::readlinkat(_dirh.native_handle().fd, _leafname.c_str(), buffer, bytes);
+#endif
+ if(read == -1)
+ {
+ return posix_error();
+ }
+ if((size_t) read == bytes)
+ {
+ if(req.kernelbuffer.empty())
+ {
+ tofill._kernel_buffer.reset();
+ size_t toallocate = tofill._kernel_buffer_size * 2;
+ auto *mem = new(std::nothrow) char[toallocate];
+ if(mem == nullptr)
+ {
+ return errc::not_enough_memory;
+ }
+ tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
+ tofill._kernel_buffer_size = toallocate;
+ continue;
+ }
+ return errc::not_enough_memory;
+ }
+ // We know we can null terminate as read < bytes
+ buffer[read] = 0;
+ tofill._link = path_view(buffer, read);
+ tofill._type = symlink_type::symbolic;
+ return std::move(tofill);
+ }
+}
+
+result<symlink_handle::const_buffers_type> symlink_handle::write(symlink_handle::io_request<symlink_handle::const_buffers_type> req, deadline d) noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ if(_devid == 0 && _inode == 0)
+ {
+ OUTCOME_TRY(_fetch_inode());
+ }
+ path_type filename;
+ OUTCOME_TRY(dirh, detail::containing_directory(std::ref(filename), *this, *this, d));
+#else
+ const path_handle &dirh = _dirh;
+ const path_type &filename = _leafname;
+#endif
+ OUTCOME_TRY(_create_symlink(dirh, filename, req.buffers.path(), d, true));
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ {
+ // Current fd now points at the symlink we just atomically replaced, so need to reopen
+ // it onto the new symlink
+ auto newthis = symlink(dirh, filename, is_writable() ? mode::write : mode::read, creation::open_existing, _flags);
+ // Prevent unlink on first close if set
+ _flags &= ~flag::unlink_on_first_close;
+ // Close myself
+ OUTCOME_TRY(close());
+ // If reopen failed, report that now
+ if(!newthis)
+ {
+ return newthis.error();
+ }
+ // Swap myself with the new this
+ swap(newthis.value());
+ }
+#endif
+ return success(std::move(req.buffers));
+}
+
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/posix/utils.ipp b/include/llfio/v2.0/detail/impl/posix/utils.ipp
index aecd0a03..61209b74 100644
--- a/include/afio/v2.0/detail/impl/posix/utils.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/utils.ipp
@@ -40,7 +40,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <sys/mman.h>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace utils
{
@@ -148,7 +148,7 @@ namespace utils
}
if(-1 == fd || ::read(fd, buffer, bytes) < static_cast<ssize_t>(bytes))
{
- AFIO_LOG_FATAL(0, "afio: Kernel crypto function failed");
+ LLFIO_LOG_FATAL(0, "llfio: Kernel crypto function failed");
std::terminate();
}
}
@@ -210,7 +210,7 @@ namespace utils
#ifndef NDEBUG
else if(ret.page_size_used > 65536)
{
- printf("afio: Large page allocation successful\n");
+ printf("llfio: Large page allocation successful\n");
}
#endif
return ret;
@@ -219,11 +219,11 @@ namespace utils
{
if(munmap(p, bytes) < 0)
{
- AFIO_LOG_FATAL(p, "afio: Freeing large pages failed");
+ LLFIO_LOG_FATAL(p, "llfio: Freeing large pages failed");
std::terminate();
}
}
} // namespace detail
} // namespace utils
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/safe_byte_ranges.ipp b/include/llfio/v2.0/detail/impl/safe_byte_ranges.ipp
index f4760896..a9dadf5a 100644
--- a/include/afio/v2.0/detail/impl/safe_byte_ranges.ipp
+++ b/include/llfio/v2.0/detail/impl/safe_byte_ranges.ipp
@@ -51,7 +51,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <mutex>
#include <unordered_map>
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace algorithm
{
@@ -141,12 +141,12 @@ namespace algorithm
public:
threaded_byte_ranges(const path_handle &base, path_view lockfile)
{
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
_h = file_handle::file(base, lockfile, file_handle::mode::write, file_handle::creation::if_needed, file_handle::caching::temporary).value();
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> _lock(entities_guard &out, deadline d, bool spin_not_sleep) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
unsigned mythreadid = QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id();
std::chrono::steady_clock::time_point began_steady;
std::chrono::system_clock::time_point end_utc;
@@ -366,9 +366,9 @@ namespace algorithm
}
// return success();
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long /*unused*/) noexcept final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(entities_type entities, unsigned long long /*unused*/) noexcept final
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
unsigned mythreadid = QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id();
std::unique_lock<decltype(_m)> guard(_m);
for(auto &entity : entities)
@@ -388,7 +388,7 @@ namespace algorithm
static threaded_byte_ranges_list v;
return v;
}
- AFIO_HEADERS_ONLY_FUNC_SPEC result<std::shared_ptr<shared_fs_mutex>> inode_to_fs_mutex(const path_handle &base, path_view lockfile) noexcept
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<std::shared_ptr<shared_fs_mutex>> inode_to_fs_mutex(const path_handle &base, path_view lockfile) noexcept
{
try
{
@@ -435,4 +435,4 @@ namespace algorithm
} // namespace shared_fs_mutex
} // namespace algorithm
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/storage_profile.ipp b/include/llfio/v2.0/detail/impl/storage_profile.ipp
index b442f74a..be8d4e5c 100644
--- a/include/afio/v2.0/detail/impl/storage_profile.ipp
+++ b/include/llfio/v2.0/detail/impl/storage_profile.ipp
@@ -47,12 +47,12 @@ Distributed under the Boost Software License, Version 1.0.
#include <iostream>
#endif
-#define AFIO_STORAGE_PROFILE_TIME_DIVIDER 10
+#define LLFIO_STORAGE_PROFILE_TIME_DIVIDER 10
// Work around buggy Windows scheduler
-//#define AFIO_STORAGE_PROFILE_PIN_THREADS
+//#define LLFIO_STORAGE_PROFILE_PIN_THREADS
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace storage_profile
{
@@ -88,7 +88,7 @@ namespace storage_profile
*/
void storage_profile::write(std::ostream &out, const std::regex &which, size_t _indent, bool invert_match) const
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
std::vector<std::string> lastsection;
auto print = [_indent, &out, &lastsection](auto &i) {
size_t indent = _indent;
@@ -194,14 +194,14 @@ namespace storage_profile
chunksize = static_cast<size_t>(sp.mem_quantity.value / 4);
}
char *buffer = utils::page_allocator<char>().allocate(chunksize);
- auto unbuffer = AFIO_V2_NAMESPACE::undoer([buffer, chunksize] { utils::page_allocator<char>().deallocate(buffer, chunksize); });
+ auto unbuffer = LLFIO_V2_NAMESPACE::undoer([buffer, chunksize] { utils::page_allocator<char>().deallocate(buffer, chunksize); });
// Make sure all memory is really allocated first
memset(buffer, 1, chunksize);
// Max bandwidth is sequential writes of min(25% of system memory or 256Mb)
auto begin = std::chrono::high_resolution_clock::now();
unsigned long long count;
- for(count = 0; std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (10 / AFIO_STORAGE_PROFILE_TIME_DIVIDER); count++)
+ for(count = 0; std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (10 / LLFIO_STORAGE_PROFILE_TIME_DIVIDER); count++)
{
memset(buffer, count & 0xff, chunksize);
}
@@ -210,7 +210,7 @@ namespace storage_profile
// Min bandwidth is randomised 4Kb copies of the same
QUICKCPPLIB_NAMESPACE::algorithm::small_prng::small_prng ctx(78);
begin = std::chrono::high_resolution_clock::now();
- for(count = 0; std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (10 / AFIO_STORAGE_PROFILE_TIME_DIVIDER); count++)
+ for(count = 0; std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (10 / LLFIO_STORAGE_PROFILE_TIME_DIVIDER); count++)
{
for(size_t n = 0; n < chunksize; n += 4096)
{
@@ -511,7 +511,7 @@ namespace storage_profile
std::cout << "direct=" << !srch.are_reads_from_cache() << " sync=" << srch.are_writes_durable() << " testing atomicity of rewrites of " << size << " bytes ..." << std::endl;
#endif
auto begin = std::chrono::high_resolution_clock::now();
- while(!failed && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (20 / AFIO_STORAGE_PROFILE_TIME_DIVIDER))
+ while(!failed && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (20 / LLFIO_STORAGE_PROFILE_TIME_DIVIDER))
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
@@ -657,7 +657,7 @@ namespace storage_profile
std::cout << "direct=" << !srch.are_reads_from_cache() << " sync=" << srch.are_writes_durable() << " testing atomicity of rewrites of " << size << " bytes to offset " << offset << " ..." << std::endl;
#endif
auto begin = std::chrono::high_resolution_clock::now();
- while(!failed && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (20 / AFIO_STORAGE_PROFILE_TIME_DIVIDER))
+ while(!failed && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (20 / LLFIO_STORAGE_PROFILE_TIME_DIVIDER))
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
@@ -818,7 +818,7 @@ namespace storage_profile
std::cout << "direct=" << !srch.are_reads_from_cache() << " sync=" << srch.are_writes_durable() << " testing atomicity of rewrites of " << size << " bytes to offset " << offset << " ..." << std::endl;
#endif
auto begin = std::chrono::high_resolution_clock::now();
- while(!failed && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (20 / AFIO_STORAGE_PROFILE_TIME_DIVIDER))
+ while(!failed && std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - begin).count() < (20 / LLFIO_STORAGE_PROFILE_TIME_DIVIDER))
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
@@ -905,7 +905,7 @@ namespace storage_profile
for(size_t no = 0; no < nowriters; no++)
{
std::packaged_task<void()> task([no, &done, &workfiles, &results] {
-#ifdef AFIO_STORAGE_PROFILE_PIN_THREADS
+#ifdef LLFIO_STORAGE_PROFILE_PIN_THREADS
SetThreadAffinityMask(GetCurrentThread(), 1ULL << (no * 2));
#endif
file_handle &h = *workfiles[no];
@@ -944,7 +944,7 @@ namespace storage_profile
for(size_t no = nowriters; no < nowriters + noreaders; no++)
{
std::packaged_task<void()> task([no, &done, &workfiles, &results] {
-#ifdef AFIO_STORAGE_PROFILE_PIN_THREADS
+#ifdef LLFIO_STORAGE_PROFILE_PIN_THREADS
SetThreadAffinityMask(GetCurrentThread(), 1ULL << (no * 2));
#endif
file_handle &h = *workfiles[no];
@@ -1191,7 +1191,7 @@ namespace storage_profile
inline outcome<stats> _traversal_N(file_handle &srch, size_t no, size_t bytes, bool cold_cache, bool race_free, bool reduced) noexcept
{
stats s;
-#ifdef AFIO_STORAGE_PROFILE_PIN_THREADS
+#ifdef LLFIO_STORAGE_PROFILE_PIN_THREADS
SetThreadAffinityMask(GetCurrentThread(), 1ULL << (no * 2));
#endif
try
@@ -1373,7 +1373,7 @@ namespace storage_profile
*/
} // namespace response_time
} // namespace storage_profile
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#ifdef WIN32
#include "windows/storage_profile.ipp"
diff --git a/include/afio/v2.0/detail/impl/windows/async_file_handle.ipp b/include/llfio/v2.0/detail/impl/windows/async_file_handle.ipp
index b70971d3..4efb577b 100644
--- a/include/afio/v2.0/detail/impl/windows/async_file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/async_file_handle.ipp
@@ -25,7 +25,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_handle::barrier(async_file_handle::io_request<async_file_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
{
@@ -49,8 +49,8 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
state_type(const state_type &) = delete;
state_type &operator=(state_type &&) = delete;
state_type &operator=(const state_type &) = delete;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC _erased_completion_handler *erased_completion_handler() noexcept override final { return completion; }
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void _system_io_completion(long errcode, long bytes_transferred, void *internal_state) noexcept override final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC _erased_completion_handler *erased_completion_handler() noexcept override final { return completion; }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void _system_io_completion(long errcode, long bytes_transferred, void *internal_state) noexcept override final
{
auto ol = static_cast<LPOVERLAPPED>(internal_state);
ol->hEvent = nullptr;
@@ -67,10 +67,10 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
size_t idx = ol - ols;
if(idx >= this->items)
{
- AFIO_LOG_FATAL(0, "async_file_handle::io_state::operator() called with invalid index");
+ LLFIO_LOG_FATAL(0, "async_file_handle::io_state::operator() called with invalid index");
std::terminate();
}
- result.value()[idx].len = bytes_transferred;
+ result.value()[idx] = {result.value()[idx].data(), (size_t) bytes_transferred};
}
}
this->parent->service()->_work_done();
@@ -80,7 +80,7 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
(*completion)(this);
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~state_type() override final
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~state_type() override final
{
// Do we need to cancel pending i/o?
if(this->items_to_go)
@@ -101,12 +101,12 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
#ifndef NDEBUG
if(res.has_error())
{
- AFIO_LOG_FATAL(0, "async_file_handle: io_service failed");
+ LLFIO_LOG_FATAL(0, "async_file_handle: io_service failed");
std::terminate();
}
if(!res.value())
{
- AFIO_LOG_FATAL(0, "async_file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(0, "async_file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -177,16 +177,16 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
}
// Use the unused hEvent member to pass through the state
ol->hEvent = reinterpret_cast<HANDLE>(state);
- offset += out[n].len;
+ offset += out[n].size();
++state->items_to_go;
#ifndef NDEBUG
if(_v.requires_aligned_io())
{
- assert((reinterpret_cast<uintptr_t>(out[n].data) & 511) == 0);
- assert((out[n].len & 511) == 0);
+ assert((reinterpret_cast<uintptr_t>(out[n].data()) & 511) == 0);
+ assert((out[n].size() & 511) == 0);
}
#endif
- if(!ioroutine(_v.h, const_cast<byte *>(out[n].data), static_cast<DWORD>(out[n].len), ol, handle_completion::Do))
+ if(!ioroutine(_v.h, const_cast<byte *>(out[n].data()), static_cast<DWORD>(out[n].size()), ol, handle_completion::Do))
{
--state->items_to_go;
state->result.write = win32_error();
@@ -221,7 +221,7 @@ result<async_file_handle::io_state_ptr> async_file_handle::_begin_io(span<char>
async_file_handle::io_result<async_file_handle::buffers_type> async_file_handle::read(async_file_handle::io_request<async_file_handle::buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
optional<io_result<buffers_type>> ret;
OUTCOME_TRY(io_state, async_read(reqs, [&ret](async_file_handle *, io_result<buffers_type> &result) { ret = result; }));
(void) io_state; // holds i/o open until it completes
@@ -238,7 +238,7 @@ async_file_handle::io_result<async_file_handle::buffers_type> async_file_handle:
#ifndef NDEBUG
if(!ret && t && !t.value())
{
- AFIO_LOG_FATAL(_v.h, "async_file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(_v.h, "async_file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -248,7 +248,7 @@ async_file_handle::io_result<async_file_handle::buffers_type> async_file_handle:
async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_handle::write(async_file_handle::io_request<async_file_handle::const_buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
optional<io_result<const_buffers_type>> ret;
OUTCOME_TRY(io_state, async_write(reqs, [&ret](async_file_handle *, io_result<const_buffers_type> &result) { ret = result; }));
(void) io_state; // holds i/o open until it completes
@@ -265,7 +265,7 @@ async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_h
#ifndef NDEBUG
if(!ret && t && !t.value())
{
- AFIO_LOG_FATAL(_v.h, "async_file_handle: io_service returns no work when i/o has not completed");
+ LLFIO_LOG_FATAL(_v.h, "async_file_handle: io_service returns no work when i/o has not completed");
std::terminate();
}
#endif
@@ -274,4 +274,4 @@ async_file_handle::io_result<async_file_handle::const_buffers_type> async_file_h
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/directory_handle.ipp b/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
index 185f5077..158bbc7f 100644
--- a/include/afio/v2.0/detail/impl/windows/directory_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
@@ -25,7 +25,7 @@ http://www.boost.org/LICENSE_1_0.txt)
#include "../../../directory_handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<directory_handle> directory_handle::directory(const path_handle &base, path_view_type path, mode _mode, creation _creation, caching _caching, flag flags) noexcept
{
@@ -37,7 +37,7 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
}
result<directory_handle> ret(directory_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::directory;
DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
// Trying to truncate a directory returns EISDIR rather than some internal Win32 error code uncomparable to errc
@@ -137,57 +137,15 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
result<directory_handle> directory_handle::clone(mode mode_, caching caching_, deadline /* unused */) const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- // Fast path
- if(mode_ == mode::unchanged && caching_ == caching::unchanged)
- {
- result<directory_handle> ret(directory_handle(native_handle_type(), _devid, _inode, _caching, _flags));
- ret.value()._v.behaviour = _v.behaviour;
- if(DuplicateHandle(GetCurrentProcess(), _v.h, GetCurrentProcess(), &ret.value()._v.h, 0, 0, DUPLICATE_SAME_ACCESS) == 0)
- {
- return win32_error();
- }
- return ret;
- }
- // Slow path
- windows_nt_kernel::init();
- using namespace windows_nt_kernel;
- result<directory_handle> ret(directory_handle(native_handle_type(), _devid, _inode, caching_, _flags));
- native_handle_type &nativeh = ret.value()._v;
- nativeh.behaviour |= native_handle_type::disposition::directory;
- DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- OUTCOME_TRY(access, access_mask_from_handle_mode(nativeh, mode_, _flags));
- OUTCOME_TRYV(attributes_from_handle_caching_and_flags(nativeh, caching_, _flags));
- /* It is super important that we remove the DELETE permission for directories as otherwise relative renames
- will always fail due to an unfortunate design choice by Microsoft.
- */
- access &= ~DELETE;
- OUTCOME_TRY(ntflags, ntflags_from_handle_caching_and_flags(nativeh, caching_, _flags));
- ntflags |= 0x01 /*FILE_DIRECTORY_FILE*/; // required to open a directory
- OBJECT_ATTRIBUTES oa{};
- memset(&oa, 0, sizeof(oa));
- oa.Length = sizeof(OBJECT_ATTRIBUTES);
- // It is entirely undocumented that this is how you clone a file handle with new privs
- UNICODE_STRING _path{};
- memset(&_path, 0, sizeof(_path));
- oa.ObjectName = &_path;
- oa.RootDirectory = _v.h;
- IO_STATUS_BLOCK isb = make_iostatus();
- NTSTATUS ntstat = NtOpenFile(&nativeh.h, access, &oa, &isb, fileshare, ntflags);
- if(STATUS_PENDING == ntstat)
- {
- ntstat = ntwait(nativeh.h, isb, deadline());
- }
- if(ntstat < 0)
- {
- return ntkernel_error(ntstat);
- }
+ LLFIO_LOG_FUNCTION_CALL(this);
+ result<directory_handle> ret(directory_handle(native_handle_type(), _devid, _inode, _caching, _flags));
+ OUTCOME_TRY(do_clone_handle(ret.value()._v, _v, mode_, caching_, _flags, true));
return ret;
}
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> directory_handle::clone_to_path_handle() const noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> directory_handle::clone_to_path_handle() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
result<path_handle> ret(path_handle(native_handle_type(), _caching, _flags));
ret.value()._v.behaviour = _v.behaviour;
if(DuplicateHandle(GetCurrentProcess(), _v.h, GetCurrentProcess(), &ret.value()._v.h, 0, 0, DUPLICATE_SAME_ACCESS) == 0)
@@ -230,7 +188,7 @@ namespace detail
result<void> directory_handle::relink(const path_handle &base, directory_handle::path_view_type newpath, bool atomic_replace, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
/* We can never hold DELETE permission on an open handle to a directory as otherwise
race free renames into that directory will fail, so we are forced to duplicate the
handle with DELETE privs temporarily in order to issue the rename
@@ -241,7 +199,7 @@ result<void> directory_handle::relink(const path_handle &base, directory_handle:
result<void> directory_handle::unlink(deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
/* We can never hold DELETE permission on an open handle to a directory as otherwise
race free renames into that directory will fail, so we are forced to duplicate the
handle with DELETE privs temporarily in order to issue the unlink
@@ -255,7 +213,7 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
static constexpr stat_t::want default_stat_contents = stat_t::want::ino | stat_t::want::type | stat_t::want::atim | stat_t::want::mtim | stat_t::want::ctim | stat_t::want::size | stat_t::want::allocated | stat_t::want::birthtim | stat_t::want::sparse | stat_t::want::compressed | stat_t::want::reparse_point;
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(tofill.empty())
{
return enumerate_info{std::move(tofill), stat_t::want::none, false};
@@ -333,7 +291,7 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
}
directory_entry &item = tofill[n];
item.leafname = path_view(wstring_view(ffdi->FileName, length));
- if(filtering == filter::fastdeleted && item.leafname.is_afio_deleted())
+ if(filtering == filter::fastdeleted && item.leafname.is_llfio_deleted())
{
continue;
}
@@ -364,4 +322,4 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/file_handle.ipp b/include/llfio/v2.0/detail/impl/windows/file_handle.ipp
index e3d7fb27..82c855ae 100644
--- a/include/afio/v2.0/detail/impl/windows/file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/file_handle.ipp
@@ -25,7 +25,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../file_handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<file_handle> file_handle::file(const path_handle &base, file_handle::path_view_type path, file_handle::mode _mode, file_handle::creation _creation, file_handle::caching _caching, file_handle::flag flags) noexcept
{
@@ -33,7 +33,7 @@ result<file_handle> file_handle::file(const path_handle &base, file_handle::path
using namespace windows_nt_kernel;
result<file_handle> ret(file_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::file;
DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
OUTCOME_TRY(access, access_mask_from_handle_mode(nativeh, _mode, flags));
@@ -155,27 +155,14 @@ result<file_handle> file_handle::file(const path_handle &base, file_handle::path
FILE_SET_SPARSE_BUFFER fssb = {1u};
if(DeviceIoControl(nativeh.h, FSCTL_SET_SPARSE, &fssb, sizeof(fssb), nullptr, 0, &bytesout, nullptr) == 0)
{
-#if AFIO_LOGGING_LEVEL >= 3
+#if LLFIO_LOGGING_LEVEL >= 3
DWORD errcode = GetLastError();
- AFIO_LOG_WARN(&ret, "Failed to set file to sparse");
+ LLFIO_LOG_WARN(&ret, "Failed to set file to sparse");
result<void> r = win32_error(errcode);
(void) r; // throw away
#endif
}
}
- if(flags & flag::unlink_on_first_close)
- {
- // Hide this item
- IO_STATUS_BLOCK isb = make_iostatus();
- FILE_BASIC_INFORMATION fbi{};
- memset(&fbi, 0, sizeof(fbi));
- fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
- NtSetInformationFile(nativeh.h, &isb, &fbi, sizeof(fbi), FileBasicInformation);
- if(flags & flag::overlapped)
- {
- ntwait(nativeh.h, isb, deadline());
- }
- }
if(_creation == creation::truncate && ret.value().are_safety_fsyncs_issued())
{
FlushFileBuffers(nativeh.h);
@@ -192,7 +179,7 @@ result<file_handle> file_handle::temp_inode(const path_handle &dirh, mode _mode,
flags |= flag::disable_safety_unlinks | flag::win_disable_unlink_emulation;
result<file_handle> ret(file_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::file;
DWORD fileshare = /* no read nor write access for others */ FILE_SHARE_DELETE;
OUTCOME_TRY(access, access_mask_from_handle_mode(nativeh, _mode, flags));
@@ -303,12 +290,12 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(fil
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(d && !_v.is_overlapped())
{
return errc::not_supported;
}
- AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
OVERLAPPED ol{};
memset(&ol, 0, sizeof(ol));
auto *isb = reinterpret_cast<IO_STATUS_BLOCK *>(&ol);
@@ -329,7 +316,7 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(fil
if(STATUS_TIMEOUT == ntstat)
{
CancelIoEx(_v.h, &ol);
- AFIO_WIN_DEADLINE_TO_TIMEOUT(d);
+ LLFIO_WIN_DEADLINE_TO_TIMEOUT(d);
}
}
if(ntstat < 0)
@@ -341,54 +328,16 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(fil
result<file_handle> file_handle::clone(mode mode_, caching caching_, deadline /*unused*/) const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- // Fast path
- if(mode_ == mode::unchanged && caching_ == caching::unchanged)
- {
- result<file_handle> ret(file_handle(native_handle_type(), _devid, _inode, caching_, _flags));
- ret.value()._service = _service;
- ret.value()._v.behaviour = _v.behaviour;
- if(DuplicateHandle(GetCurrentProcess(), _v.h, GetCurrentProcess(), &ret.value()._v.h, 0, 0, DUPLICATE_SAME_ACCESS) == 0)
- {
- return win32_error();
- }
- return ret;
- }
- // Slow path
- windows_nt_kernel::init();
- using namespace windows_nt_kernel;
+ LLFIO_LOG_FUNCTION_CALL(this);
result<file_handle> ret(file_handle(native_handle_type(), _devid, _inode, caching_, _flags));
- native_handle_type &nativeh = ret.value()._v;
- nativeh.behaviour |= native_handle_type::disposition::file;
- DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- OUTCOME_TRY(access, access_mask_from_handle_mode(nativeh, mode_, _flags));
- OUTCOME_TRYV(attributes_from_handle_caching_and_flags(nativeh, caching_, _flags));
- OUTCOME_TRY(ntflags, ntflags_from_handle_caching_and_flags(nativeh, caching_, _flags));
- ntflags |= 0x040 /*FILE_NON_DIRECTORY_FILE*/; // do not open a directory
- OBJECT_ATTRIBUTES oa{};
- memset(&oa, 0, sizeof(oa));
- oa.Length = sizeof(OBJECT_ATTRIBUTES);
- // It is entirely undocumented that this is how you clone a file handle with new privs
- UNICODE_STRING _path{};
- memset(&_path, 0, sizeof(_path));
- oa.ObjectName = &_path;
- oa.RootDirectory = _v.h;
- IO_STATUS_BLOCK isb = make_iostatus();
- NTSTATUS ntstat = NtOpenFile(&nativeh.h, access, &oa, &isb, fileshare, ntflags);
- if(STATUS_PENDING == ntstat)
- {
- ntstat = ntwait(nativeh.h, isb, deadline());
- }
- if(ntstat < 0)
- {
- return ntkernel_error(ntstat);
- }
+ ret.value()._service = _service;
+ OUTCOME_TRY(do_clone_handle(ret.value()._v, _v, mode_, caching_, _flags));
return ret;
}
result<file_handle::extent_type> file_handle::maximum_extent() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
#if 0
char buffer[1];
DWORD read = 0;
@@ -407,7 +356,7 @@ result<file_handle::extent_type> file_handle::maximum_extent() const noexcept
result<file_handle::extent_type> file_handle::truncate(file_handle::extent_type newsize) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
FILE_END_OF_FILE_INFO feofi{};
feofi.EndOfFile.QuadPart = newsize;
if(SetFileInformationByHandle(_v.h, FileEndOfFileInfo, &feofi, sizeof(feofi)) == 0)
@@ -425,7 +374,7 @@ result<std::vector<std::pair<file_handle::extent_type, file_handle::extent_type>
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
try
{
static_assert(sizeof(std::pair<file_handle::extent_type, file_handle::extent_type>) == sizeof(FILE_ALLOCATED_RANGE_BUFFER), "FILE_ALLOCATED_RANGE_BUFFER is not equivalent to pair<extent_type, extent_type>!");
@@ -466,7 +415,7 @@ result<file_handle::extent_type> file_handle::zero(file_handle::extent_type offs
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(offset + bytes < offset)
{
return errc::value_too_large;
@@ -496,4 +445,4 @@ result<file_handle::extent_type> file_handle::zero(file_handle::extent_type offs
return success();
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/fs_handle.ipp b/include/llfio/v2.0/detail/impl/windows/fs_handle.ipp
index c3b47873..e42283e3 100644
--- a/include/afio/v2.0/detail/impl/windows/fs_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/fs_handle.ipp
@@ -27,7 +27,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../utils.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<void> fs_handle::_fetch_inode() const noexcept
{
@@ -42,9 +42,9 @@ result<path_handle> fs_handle::parent_path_handle(deadline d) const noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
auto &h = _get_handle();
- AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
if(_devid == 0 && _inode == 0)
{
OUTCOME_TRY(_fetch_inode());
@@ -73,7 +73,7 @@ result<path_handle> fs_handle::parent_path_handle(deadline d) const noexcept
continue;
}
path_handle currentdirh = std::move(currentdirh_.value());
- if(h.flags() & handle::flag::disable_safety_unlinks)
+ if((h.flags() & handle::flag::disable_safety_unlinks) != 0 || h.is_symlink())
{
return success(std::move(currentdirh));
}
@@ -116,7 +116,7 @@ result<path_handle> fs_handle::parent_path_handle(deadline d) const noexcept
{
return success(std::move(currentdirh));
}
- AFIO_WIN_DEADLINE_TO_TIMEOUT(d);
+ LLFIO_WIN_DEADLINE_TO_TIMEOUT(d);
}
}
catch(...)
@@ -129,7 +129,7 @@ result<void> fs_handle::relink(const path_handle &base, path_view_type path, boo
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
auto &h = _get_handle();
// If the target is a win32 path, we need to convert to NT path and call ourselves
@@ -186,7 +186,7 @@ result<void> fs_handle::unlink(deadline d) noexcept
using flag = handle::flag;
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
auto &h = _get_handle();
HANDLE duph;
// Try by POSIX delete first
@@ -200,7 +200,10 @@ result<void> fs_handle::unlink(deadline d) noexcept
oa.ObjectName = &_path;
oa.RootDirectory = h.native_handle().h;
IO_STATUS_BLOCK isb = make_iostatus();
- NTSTATUS ntstat = NtOpenFile(&duph, SYNCHRONIZE | DELETE, &oa, &isb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0x20 /*FILE_SYNCHRONOUS_IO_NONALERT*/);
+ DWORD ntflags = 0x20 /*FILE_SYNCHRONOUS_IO_NONALERT*/;
+ if(h.is_symlink())
+ ntflags |= 0x00200000 /*FILE_OPEN_REPARSE_POINT*/;
+ NTSTATUS ntstat = NtOpenFile(&duph, SYNCHRONIZE | DELETE, &oa, &isb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, ntflags);
if(ntstat < 0)
{
return ntkernel_error(ntstat);
@@ -244,7 +247,7 @@ result<void> fs_handle::unlink(deadline d) noexcept
// This error also annoyingly appears if the file has delete on close set on it already
if(out.error().value() == static_cast<int>(0xC0000043) /*STATUS_SHARING_VIOLATION*/)
{
- AFIO_LOG_WARN(this, "Failed to rename entry to random name to simulate immediate unlinking due to STATUS_SHARING_VIOLATION, skipping");
+ LLFIO_LOG_WARN(this, "Failed to rename entry to random name to simulate immediate unlinking due to STATUS_SHARING_VIOLATION, skipping");
}
else
{
@@ -287,4 +290,4 @@ result<void> fs_handle::unlink(deadline d) noexcept
return success();
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/handle.ipp b/include/llfio/v2.0/detail/impl/windows/handle.ipp
index 72eda554..e3d0e851 100644
--- a/include/afio/v2.0/detail/impl/windows/handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/handle.ipp
@@ -25,7 +25,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
handle::~handle()
{
@@ -35,7 +35,7 @@ handle::~handle()
auto ret = handle::close();
if(ret.has_error())
{
- AFIO_LOG_FATAL(_v.h, "handle::~handle() close failed");
+ LLFIO_LOG_FATAL(_v.h, "handle::~handle() close failed");
abort();
}
}
@@ -43,7 +43,7 @@ handle::~handle()
result<handle::path_type> handle::current_path() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
try
{
// Most efficient, least memory copying method is direct fill of a wstring which is moved into filesystem::path
@@ -72,9 +72,17 @@ result<handle::path_type> handle::current_path() const noexcept
result<void> handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_v)
{
+#ifndef NDEBUG
+ // Trap when refined handle implementations don't set their vptr properly (this took a while to debug!)
+ if((static_cast<unsigned>(_v.behaviour) & 0xff00) != 0 && !(_v.behaviour & native_handle_type::disposition::_child_close_executed))
+ {
+ LLFIO_LOG_FATAL(this, "handle::close() called on a derived handle implementation, this suggests vptr is incorrect");
+ abort();
+ }
+#endif
if(are_safety_fsyncs_issued() && is_writable())
{
if(FlushFileBuffers(_v.h) == 0)
@@ -93,7 +101,7 @@ result<void> handle::close() noexcept
result<handle> handle::clone() const noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
result<handle> ret(handle(native_handle_type(), _caching, _flags));
ret.value()._v.behaviour = _v.behaviour;
if(DuplicateHandle(GetCurrentProcess(), _v.h, GetCurrentProcess(), &ret.value()._v.h, 0, 0, DUPLICATE_SAME_ACCESS) == 0)
@@ -105,7 +113,7 @@ result<handle> handle::clone() const noexcept
result<void> handle::set_append_only(bool enable) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// This works only due to special handling in OVERLAPPED later
if(enable)
{
@@ -120,4 +128,4 @@ result<void> handle::set_append_only(bool enable) noexcept
return success();
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/import.hpp b/include/llfio/v2.0/detail/impl/windows/import.hpp
index dbdaaa91..c7ccf165 100644
--- a/include/afio/v2.0/detail/impl/windows/import.hpp
+++ b/include/llfio/v2.0/detail/impl/windows/import.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_WINDOWS_H
-#define AFIO_WINDOWS_H
+#ifndef LLFIO_WINDOWS_H
+#define LLFIO_WINDOWS_H
#include "../../../handle.hpp"
#include <memory> // for unique_ptr
@@ -51,18 +51,18 @@ Distributed under the Boost Software License, Version 1.0.
#error todo
#endif
-#if !AFIO_EXPERIMENTAL_STATUS_CODE
+#if !LLFIO_EXPERIMENTAL_STATUS_CODE
// Bring in the custom NT kernel error code category
-#if AFIO_HEADERS_ONLY
+#if LLFIO_HEADERS_ONLY
#define NTKERNEL_ERROR_CATEGORY_INLINE
#define NTKERNEL_ERROR_CATEGORY_STATIC
#endif
#include "../../../../ntkernel-error-category/include/ntkernel_category.hpp"
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-#if AFIO_EXPERIMENTAL_STATUS_CODE
+#if LLFIO_EXPERIMENTAL_STATUS_CODE
#else
//! Helper for constructing an error info from a DWORD
inline error_info win32_error(DWORD c = GetLastError())
@@ -776,7 +776,7 @@ namespace windows_nt_kernel
{
DiscardVirtualMemory_ = reinterpret_cast<DiscardVirtualMemory_t>(GetProcAddress(kernel32, "DiscardVirtualMemory"));
}
-#ifdef AFIO_OP_STACKBACKTRACEDEPTH
+#ifdef LLFIO_OP_STACKBACKTRACEDEPTH
if(dbghelp)
{
HMODULE dbghelp = LoadLibraryA("DBGHELP.DLL");
@@ -828,7 +828,7 @@ namespace windows_nt_kernel
inline filesystem::file_type to_st_type(ULONG FileAttributes, ULONG ReparsePointTag)
{
-#ifdef AFIO_USE_LEGACY_FILESYSTEM_SEMANTICS
+#ifdef LLFIO_USE_LEGACY_FILESYSTEM_SEMANTICS
if(FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && (ReparsePointTag == IO_REPARSE_TAG_MOUNT_POINT || ReparsePointTag == IO_REPARSE_TAG_SYMLINK))
return filesystem::file_type::symlink_file;
// return filesystem::file_type::reparse_file;
@@ -910,7 +910,7 @@ namespace windows_nt_kernel
} // namespace windows_nt_kernel
#if 0
-inline void fill_stat_t(stat_t &stat, AFIO_POSIX_STAT_STRUCT s, metadata_flags wanted)
+inline void fill_stat_t(stat_t &stat, LLFIO_POSIX_STAT_STRUCT s, metadata_flags wanted)
{
#ifndef _WIN32
if (!!(wanted&metadata_flags::dev)) { stat.st_dev = s.st_dev; }
@@ -958,7 +958,7 @@ inline HANDLE get_thread_local_waitable_timer()
- sleep_interval: Set to the number of steady milliseconds until the sleep must end
- sleep_object: Set to a primed deadline timer HANDLE which will signal when the system clock reaches the deadline
*/
-#define AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d) \
+#define LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d) \
std::chrono::steady_clock::time_point began_steady; \
\
std::chrono::system_clock::time_point end_utc; \
@@ -977,7 +977,7 @@ DWORD sleep_interval = INFINITE;
\
HANDLE sleep_object = nullptr;
-#define AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d) \
+#define LLFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d) \
\
if(d) \
\
@@ -1001,7 +1001,7 @@ if(d)
\
}
-#define AFIO_WIN_DEADLINE_TO_TIMEOUT(type, d) \
+#define LLFIO_WIN_DEADLINE_TO_TIMEOUT(type, d) \
\
if(d) \
\
@@ -1025,7 +1025,7 @@ if(d)
- sleep_interval: Set to the number of steady milliseconds until the sleep must end
- sleep_object: Set to a primed deadline timer HANDLE which will signal when the system clock reaches the deadline
*/
-#define AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d) \
+#define LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d) \
std::chrono::steady_clock::time_point began_steady; \
\
std::chrono::system_clock::time_point end_utc; \
@@ -1050,7 +1050,7 @@ if(d)
\
}
-#define AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d) \
+#define LLFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d) \
if((d) && (d).steady) \
{ \
std::chrono::nanoseconds ns = std::chrono::duration_cast<std::chrono::nanoseconds>((began_steady + std::chrono::nanoseconds((d).nsecs)) - std::chrono::steady_clock::now()); \
@@ -1060,22 +1060,7 @@ if(d)
_timeout.QuadPart = ns.count() / -100; \
}
-#define AFIO_WIN_DEADLINE_TO_PARTIAL_DEADLINE(nd, d) \
- if(d) \
- { \
- if((d).steady) \
- { \
- std::chrono::nanoseconds ns = std::chrono::duration_cast<std::chrono::nanoseconds>((began_steady + std::chrono::nanoseconds((d).nsecs)) - std::chrono::steady_clock::now()); \
- if(ns.count() < 0) \
- (nd).nsecs = 0; \
- else \
- (nd).nsecs = ns.count(); \
- } \
- else \
- (nd) = (d); \
- }
-
-#define AFIO_WIN_DEADLINE_TO_TIMEOUT(d) \
+#define LLFIO_WIN_DEADLINE_TO_TIMEOUT(d) \
\
if(d) \
\
@@ -1108,10 +1093,10 @@ inline NTSTATUS ntwait(HANDLE h, windows_nt_kernel::IO_STATUS_BLOCK &isb, const
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
do // needs to be a do, not while in order to flip auto reset event objects etc.
{
- AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d);
// Pump alerts and APCs
NTSTATUS ntstat = NtWaitForSingleObject(h, 1u, timeout);
if(STATUS_TIMEOUT == ntstat)
@@ -1135,12 +1120,12 @@ inline bool ntsleep(const deadline &d, bool return_on_alert = false) noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
alignas(8) LARGE_INTEGER infinity{};
infinity.QuadPart = INT64_MIN;
for(;;)
{
- AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d);
// Pump alerts and APCs
NTSTATUS ntstat = NtDelayExecution(1u, timeout != nullptr ? timeout : &infinity);
(void) ntstat;
@@ -1296,6 +1281,55 @@ inline result<DWORD> ntflags_from_handle_caching_and_flags(native_handle_type &n
return ntflags;
}
+inline result<void> do_clone_handle(native_handle_type &dest, const native_handle_type &src, handle::mode mode_, handle::caching caching_, handle::flag _flags, bool isdir = false) noexcept
+{
+ // Fast path
+ if(mode_ == handle::mode::unchanged && caching_ == handle::caching::unchanged)
+ {
+ dest.behaviour = src.behaviour;
+ if(DuplicateHandle(GetCurrentProcess(), dest.h, GetCurrentProcess(), const_cast<HANDLE *>(&src.h), 0, 0, DUPLICATE_SAME_ACCESS) == 0)
+ {
+ return win32_error();
+ }
+ return success();
+ }
+ // Slow path
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ dest.behaviour |= src.behaviour & ~127U; // propagate type of handle only
+ DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ OUTCOME_TRY(access, access_mask_from_handle_mode(dest, mode_, _flags));
+ OUTCOME_TRYV(attributes_from_handle_caching_and_flags(dest, caching_, _flags));
+ if(isdir)
+ {
+ /* It is super important that we remove the DELETE permission for directories as otherwise relative renames
+ will always fail due to an unfortunate design choice by Microsoft.
+ */
+ access &= ~DELETE;
+ }
+ OUTCOME_TRY(ntflags, ntflags_from_handle_caching_and_flags(dest, caching_, _flags));
+ ntflags |= 0x040 /*FILE_NON_DIRECTORY_FILE*/; // do not open a directory
+ OBJECT_ATTRIBUTES oa{};
+ memset(&oa, 0, sizeof(oa));
+ oa.Length = sizeof(OBJECT_ATTRIBUTES);
+ // It is entirely undocumented that this is how you clone a file handle with new privs
+ UNICODE_STRING _path{};
+ memset(&_path, 0, sizeof(_path));
+ oa.ObjectName = &_path;
+ oa.RootDirectory = src.h;
+ IO_STATUS_BLOCK isb = make_iostatus();
+ NTSTATUS ntstat = NtOpenFile(&dest.h, access, &oa, &isb, fileshare, ntflags);
+ if(STATUS_PENDING == ntstat)
+ {
+ ntstat = ntwait(dest.h, isb, deadline());
+ }
+ if(ntstat < 0)
+ {
+ return ntkernel_error(ntstat);
+ }
+ return success();
+}
+
/* Our own custom CreateFileW() implementation.
The Win32 CreateFileW() implementation is unfortunately slow. It also, very annoyingly,
@@ -1473,6 +1507,6 @@ inline bool running_under_suid_gid()
return EqualSid(tu->User.Sid, to->Owner) == 0;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/afio/v2.0/detail/impl/windows/io_handle.ipp b/include/llfio/v2.0/detail/impl/windows/io_handle.ipp
index 71f51ccb..d1ec4e34 100644
--- a/include/afio/v2.0/detail/impl/windows/io_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/io_handle.ipp
@@ -25,7 +25,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../io_handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
size_t io_handle::max_buffers() const noexcept
{
@@ -43,7 +43,7 @@ template <class BuffersType, class Syscall> inline io_handle::io_result<BuffersT
return errc::argument_list_too_long;
}
- AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
std::array<OVERLAPPED, 64> _ols{};
memset(_ols.data(), 0, reqs.buffers.size() * sizeof(OVERLAPPED));
span<OVERLAPPED> ols(_ols.data(), reqs.buffers.size());
@@ -84,26 +84,26 @@ template <class BuffersType, class Syscall> inline io_handle::io_result<BuffersT
#ifndef NDEBUG
if(nativeh.requires_aligned_io())
{
- assert(((uintptr_t) req.data & 511) == 0);
- assert((req.len & 511) == 0);
+ assert(((uintptr_t) req.data() & 511) == 0);
+ assert((req.size() & 511) == 0);
}
#endif
- if(!syscall(nativeh.h, req.data, static_cast<DWORD>(req.len), &transferred, &ol) && ERROR_IO_PENDING != GetLastError())
+ if(!syscall(nativeh.h, req.data(), static_cast<DWORD>(req.size()), &transferred, &ol) && ERROR_IO_PENDING != GetLastError())
{
return win32_error();
}
- reqs.offset += req.len;
+ reqs.offset += req.size();
}
// If handle is overlapped, wait for completion of each i/o.
if(nativeh.is_overlapped())
{
for(auto &ol : ols)
{
- deadline nd = d;
- AFIO_WIN_DEADLINE_TO_PARTIAL_DEADLINE(nd, d);
+ deadline nd;
+ LLFIO_DEADLINE_TO_PARTIAL_DEADLINE(nd, d);
if(STATUS_TIMEOUT == ntwait(nativeh.h, ol, nd))
{
- AFIO_WIN_DEADLINE_TO_TIMEOUT(d);
+ LLFIO_WIN_DEADLINE_TO_TIMEOUT(d);
}
}
}
@@ -116,26 +116,26 @@ template <class BuffersType, class Syscall> inline io_handle::io_result<BuffersT
{
return ntkernel_error(static_cast<NTSTATUS>(ols[n].Internal));
}
- reqs.buffers[n].len = ols[n].InternalHigh;
+ reqs.buffers[n] = {reqs.buffers[n].data(), ols[n].InternalHigh};
}
return io_handle::io_result<BuffersType>(std::move(reqs.buffers));
}
io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_request<io_handle::buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
return do_read_write(_v, &ReadFile, reqs, d);
}
io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::io_request<io_handle::const_buffers_type> reqs, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
return do_read_write(_v, &WriteFile, reqs, d);
}
result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, io_handle::extent_type bytes, bool exclusive, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(_v.h);
+ LLFIO_LOG_FUNCTION_CALL(_v.h);
if(d && d.nsecs > 0 && !_v.is_overlapped())
{
return errc::not_supported;
@@ -145,7 +145,7 @@ result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, i
{
flags |= LOCKFILE_FAIL_IMMEDIATELY;
}
- AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ LLFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
OVERLAPPED ol{};
memset(&ol, 0, sizeof(ol));
ol.Internal = static_cast<ULONG_PTR>(-1);
@@ -169,7 +169,7 @@ result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, i
{
if(STATUS_TIMEOUT == ntwait(_v.h, ol, d))
{
- AFIO_WIN_DEADLINE_TO_TIMEOUT(d);
+ LLFIO_WIN_DEADLINE_TO_TIMEOUT(d);
}
// It seems the NT kernel is guilty of casting bugs sometimes
ol.Internal = ol.Internal & 0xffffffff;
@@ -183,7 +183,7 @@ result<io_handle::extent_guard> io_handle::lock(io_handle::extent_type offset, i
void io_handle::unlock(io_handle::extent_type offset, io_handle::extent_type bytes) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
OVERLAPPED ol{};
memset(&ol, 0, sizeof(ol));
ol.Internal = static_cast<ULONG_PTR>(-1);
@@ -197,7 +197,7 @@ void io_handle::unlock(io_handle::extent_type offset, io_handle::extent_type byt
{
auto ret = win32_error();
(void) ret;
- AFIO_LOG_FATAL(_v.h, "io_handle::unlock() failed");
+ LLFIO_LOG_FATAL(_v.h, "io_handle::unlock() failed");
std::terminate();
}
}
@@ -211,10 +211,10 @@ void io_handle::unlock(io_handle::extent_type offset, io_handle::extent_type byt
ol.Internal = ol.Internal & 0xffffffff;
auto ret = ntkernel_error(static_cast<NTSTATUS>(ol.Internal));
(void) ret;
- AFIO_LOG_FATAL(_v.h, "io_handle::unlock() failed");
+ LLFIO_LOG_FATAL(_v.h, "io_handle::unlock() failed");
std::terminate();
}
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/io_service.ipp b/include/llfio/v2.0/detail/impl/windows/io_service.ipp
index 4003e1bb..9832fff1 100644
--- a/include/afio/v2.0/detail/impl/windows/io_service.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/io_service.ipp
@@ -25,12 +25,12 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../io_service.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
io_service::io_service()
: _work_queued(0)
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &_threadh, 0, 0, DUPLICATE_SAME_ACCESS) == 0)
{
throw std::runtime_error("Failed to create creating thread handle");
@@ -40,7 +40,7 @@ io_service::io_service()
io_service::~io_service()
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_work_queued != 0u)
{
fprintf(stderr, "WARNING: ~io_service() sees work still queued, blocking until no work queued\n");
@@ -54,7 +54,7 @@ io_service::~io_service()
result<bool> io_service::run_until(deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_work_queued == 0u)
{
return false;
@@ -69,7 +69,7 @@ result<bool> io_service::run_until(deadline d) noexcept
void io_service::_post(detail::function_ptr<void(io_service *)> &&f)
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
void *data = nullptr;
{
post_info pi(this, std::move(f));
@@ -99,4 +99,4 @@ void io_service::_post(detail::function_ptr<void(io_service *)> &&f)
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/map_handle.ipp b/include/llfio/v2.0/detail/impl/windows/map_handle.ipp
index ef7b7a56..e1661072 100644
--- a/include/afio/v2.0/detail/impl/windows/map_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/map_handle.ipp
@@ -40,7 +40,7 @@ Distributed under the Boost Software License, Version 1.0.
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
section_handle::~section_handle()
{
@@ -49,16 +49,20 @@ section_handle::~section_handle()
auto ret = section_handle::close();
if(ret.has_error())
{
- AFIO_LOG_FATAL(_v.h, "section_handle::~section_handle() close failed");
+ LLFIO_LOG_FATAL(_v.h, "section_handle::~section_handle() close failed");
abort();
}
}
}
result<void> section_handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_v)
{
+#ifndef NDEBUG
+ // Tell handle::close() that we have correctly executed
+ _v.behaviour |= native_handle_type::disposition::_child_close_executed;
+#endif
OUTCOME_TRYV(handle::close());
OUTCOME_TRYV(_anonymous.close());
_flag = flag::none;
@@ -154,7 +158,7 @@ result<section_handle> section_handle::section(file_handle &backing, extent_type
{
pmaximum_size = nullptr;
}
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
HANDLE h;
NTSTATUS ntstat = NtCreateSection(&h, SECTION_ALL_ACCESS, poa, pmaximum_size, prot, attribs, backing.native_handle().h);
if(ntstat < 0)
@@ -226,7 +230,7 @@ result<section_handle> section_handle::section(extent_type bytes, const path_han
nativeh.behaviour |= native_handle_type::disposition::section;
LARGE_INTEGER _maximum_size{}, *pmaximum_size = &_maximum_size;
_maximum_size.QuadPart = bytes;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
HANDLE h;
NTSTATUS ntstat = NtCreateSection(&h, SECTION_ALL_ACCESS, nullptr, pmaximum_size, prot, attribs, anonh.native_handle().h);
if(ntstat < 0)
@@ -241,7 +245,7 @@ result<section_handle::extent_type> section_handle::length() const noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
SECTION_BASIC_INFORMATION sbi{};
NTSTATUS ntstat = NtQuerySection(_v.h, SectionBasicInformation, &sbi, sizeof(sbi), nullptr);
if(STATUS_SUCCESS != ntstat)
@@ -255,7 +259,7 @@ result<section_handle::extent_type> section_handle::truncate(extent_type newsize
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(newsize == 0u)
{
if(_backing != nullptr)
@@ -284,7 +288,7 @@ result<section_handle::extent_type> section_handle::truncate(extent_type newsize
template <class T> static inline T win32_round_up_to_allocation_size(T i) noexcept
{
// Should we fetch the allocation granularity from Windows? I very much doubt it'll ever change from 64Kb
- i = (T)((AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i) + 65535) & ~(65535)); // NOLINT
+ i = (T)((LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i) + 65535) & ~(65535)); // NOLINT
return i;
}
static inline void win32_map_flags(native_handle_type &nativeh, DWORD &allocation, DWORD &prot, size_t &commitsize, bool enable_reservation, section_handle::flag _flag)
@@ -383,7 +387,7 @@ map_handle::~map_handle()
auto ret = map_handle::close();
if(ret.has_error())
{
- AFIO_LOG_FATAL(_v.h, "map_handle::~map_handle() close failed");
+ LLFIO_LOG_FATAL(_v.h, "map_handle::~map_handle() close failed");
abort();
}
}
@@ -393,7 +397,7 @@ result<void> map_handle::close() noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_addr != nullptr)
{
if(_section != nullptr)
@@ -425,7 +429,7 @@ result<void> map_handle::close() noexcept
native_handle_type map_handle::release() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// We don't want ~handle() to close our borrowed handle
_v = native_handle_type();
_addr = nullptr;
@@ -435,17 +439,17 @@ native_handle_type map_handle::release() noexcept
map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_handle::io_request<map_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
extent_type bytes = 0;
// Check for overflow
for(const auto &req : reqs.buffers)
{
- if(bytes + req.len < bytes)
+ if(bytes + req.size() < bytes)
{
return errc::value_too_large;
}
- bytes += req.len;
+ bytes += req.size();
}
// bytes = 0 means flush entire mapping
if(bytes == 0)
@@ -456,7 +460,7 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_ha
if(!and_metadata && is_nvram())
{
auto synced = barrier({addr, bytes});
- if(synced.len >= bytes)
+ if(synced.size() >= bytes)
{
return {reqs.buffers};
}
@@ -477,8 +481,9 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_ha
}
-result<map_handle> map_handle::map(size_type bytes, section_handle::flag _flag) noexcept
+result<map_handle> map_handle::map(size_type bytes, bool /*unused*/, section_handle::flag _flag) noexcept
{
+ // TODO: Keep a cache of DiscardVirtualMemory()/MEM_RESET pages deallocated
bytes = win32_round_up_to_allocation_size(bytes);
result<map_handle> ret(map_handle(nullptr));
native_handle_type &nativeh = ret.value()._v;
@@ -488,7 +493,7 @@ result<map_handle> map_handle::map(size_type bytes, section_handle::flag _flag)
size_t commitsize;
win32_map_flags(nativeh, allocation, prot, commitsize, true, _flag);
}
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
addr = VirtualAlloc(nullptr, bytes, allocation, prot);
if(addr == nullptr)
{
@@ -532,7 +537,7 @@ result<map_handle> map_handle::map(section_handle &section, size_type bytes, ext
_offset.QuadPart = offset;
SIZE_T _bytes = utils::round_up_to_page_size(bytes);
win32_map_flags(nativeh, allocation, prot, commitsize, section.backing() != nullptr, _flag);
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
NTSTATUS ntstat = NtMapViewOfSection(section.native_handle().h, GetCurrentProcess(), &addr, 0, commitsize, &_offset, &_bytes, ViewUnmap, allocation, prot);
if(ntstat < 0)
{
@@ -569,7 +574,7 @@ result<map_handle::size_type> map_handle::truncate(size_type newsize, bool /* un
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
newsize = win32_round_up_to_allocation_size(newsize);
if(newsize == _reservation)
{
@@ -645,15 +650,15 @@ result<map_handle::size_type> map_handle::truncate(size_type newsize, bool /* un
result<map_handle::buffer_type> map_handle::commit(buffer_type region, section_handle::flag flag) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- if(region.data == nullptr)
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
DWORD prot = 0;
if(flag == section_handle::flag::none)
{
- OUTCOME_TRYV(win32_maps_apply(region.data, region.len, [](byte *addr, size_t bytes) -> result<void> {
+ OUTCOME_TRYV(win32_maps_apply(region.data(), region.size(), [](byte *addr, size_t bytes) -> result<void> {
DWORD _ = 0;
if(VirtualProtect(addr, bytes, PAGE_NOACCESS, &_) == 0)
{
@@ -680,7 +685,7 @@ result<map_handle::buffer_type> map_handle::commit(buffer_type region, section_h
prot = PAGE_EXECUTE;
}
region = utils::round_to_page_size(region);
- OUTCOME_TRYV(win32_maps_apply(region.data, region.len, [prot](byte *addr, size_t bytes) -> result<void> {
+ OUTCOME_TRYV(win32_maps_apply(region.data(), region.size(), [prot](byte *addr, size_t bytes) -> result<void> {
if(VirtualAlloc(addr, bytes, MEM_COMMIT, prot) == nullptr)
{
return win32_error();
@@ -692,13 +697,13 @@ result<map_handle::buffer_type> map_handle::commit(buffer_type region, section_h
result<map_handle::buffer_type> map_handle::decommit(buffer_type region) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
- if(region.data == nullptr)
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
region = utils::round_to_page_size(region);
- OUTCOME_TRYV(win32_maps_apply(region.data, region.len, [](byte *addr, size_t bytes) -> result<void> {
+ OUTCOME_TRYV(win32_maps_apply(region.data(), region.size(), [](byte *addr, size_t bytes) -> result<void> {
if(VirtualFree(addr, bytes, MEM_DECOMMIT) == 0)
{
return win32_error();
@@ -712,19 +717,19 @@ result<void> map_handle::zero_memory(buffer_type region) noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
- if(region.data == nullptr)
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
// Alas, zero() will not work on mapped views on Windows :(, so memset to zero and call discard if available
- memset(region.data, 0, region.len);
- if((DiscardVirtualMemory_ != nullptr) && region.len >= utils::page_size())
+ memset(region.data(), 0, region.size());
+ if((DiscardVirtualMemory_ != nullptr) && region.size() >= utils::page_size())
{
region = utils::round_to_page_size(region);
- if(region.len > 0)
+ if(region.size() > 0)
{
- OUTCOME_TRYV(win32_maps_apply(region.data, region.len, [](byte *addr, size_t bytes) -> result<void> {
+ OUTCOME_TRYV(win32_maps_apply(region.data(), region.size(), [](byte *addr, size_t bytes) -> result<void> {
if(DiscardVirtualMemory_(addr, bytes) == 0)
{
return win32_error();
@@ -740,7 +745,7 @@ result<span<map_handle::buffer_type>> map_handle::prefetch(span<buffer_type> reg
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
if(PrefetchVirtualMemory_ == nullptr)
{
return span<map_handle::buffer_type>();
@@ -757,9 +762,9 @@ result<map_handle::buffer_type> map_handle::do_not_store(buffer_type region) noe
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(0);
+ LLFIO_LOG_FUNCTION_CALL(0);
region = utils::round_to_page_size(region);
- if(region.data == nullptr)
+ if(region.data() == nullptr)
{
return errc::invalid_argument;
}
@@ -769,7 +774,7 @@ result<map_handle::buffer_type> map_handle::do_not_store(buffer_type region) noe
// Win8's DiscardVirtualMemory is much faster if it's available
if(DiscardVirtualMemory_ != nullptr)
{
- OUTCOME_TRYV(win32_maps_apply(region.data, region.len, [](byte *addr, size_t bytes) -> result<void> {
+ OUTCOME_TRYV(win32_maps_apply(region.data(), region.size(), [](byte *addr, size_t bytes) -> result<void> {
if(DiscardVirtualMemory_(addr, bytes) == 0)
{
return win32_error();
@@ -779,7 +784,7 @@ result<map_handle::buffer_type> map_handle::do_not_store(buffer_type region) noe
return region;
}
// Else MEM_RESET will do
- OUTCOME_TRYV(win32_maps_apply(region.data, region.len, [](byte *addr, size_t bytes) -> result<void> {
+ OUTCOME_TRYV(win32_maps_apply(region.data(), region.size(), [](byte *addr, size_t bytes) -> result<void> {
if(VirtualAlloc(addr, bytes, MEM_RESET, 0) == nullptr)
{
return win32_error();
@@ -789,30 +794,30 @@ result<map_handle::buffer_type> map_handle::do_not_store(buffer_type region) noe
return region;
}
// We did nothing
- region.len = 0;
+ region = {region.data(), 0};
return region;
}
map_handle::io_result<map_handle::buffers_type> map_handle::read(io_request<buffers_type> reqs, deadline /*d*/) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
for(buffer_type &req : reqs.buffers)
{
if(togo != 0u)
{
- req.data = addr;
- if(req.len > togo)
+ req = {addr, req.size()};
+ if(req.size() > togo)
{
- req.len = togo;
+ req = {req.data(), togo};
}
- addr += req.len;
- togo -= req.len;
+ addr += req.size();
+ togo -= req.size();
}
else
{
- req.len = 0;
+ req = {req.data(), 0};
}
}
return reqs.buffers;
@@ -820,7 +825,7 @@ map_handle::io_result<map_handle::buffers_type> map_handle::read(io_request<buff
map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_request<const_buffers_type> reqs, deadline /*d*/) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
if(QUICKCPPLIB_NAMESPACE::signal_guard::signal_guard(QUICKCPPLIB_NAMESPACE::signal_guard::signalc::undefined_memory_access,
@@ -829,18 +834,18 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_reque
{
if(togo != 0u)
{
- if(req.len > togo)
+ if(req.size() > togo)
{
- req.len = togo;
+ req = {req.data(), togo};
}
- memcpy(addr, req.data, req.len);
- req.data = addr;
- addr += req.len;
- togo -= req.len;
+ memcpy(addr, req.data(), req.size());
+ req = {addr, req.size()};
+ addr += req.size();
+ togo -= req.size();
}
else
{
- req.len = 0;
+ req = {req.data(), 0};
}
}
return false;
@@ -861,4 +866,4 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_reque
return reqs.buffers;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/mapped_file_handle.ipp b/include/llfio/v2.0/detail/impl/windows/mapped_file_handle.ipp
index 5f1d815d..20493a45 100644
--- a/include/afio/v2.0/detail/impl/windows/mapped_file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/mapped_file_handle.ipp
@@ -25,11 +25,11 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../mapped_file_handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<mapped_file_handle::size_type> mapped_file_handle::reserve(size_type reservation) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(reservation == 0)
{
OUTCOME_TRY(length, underlying_file_maximum_extent());
@@ -66,7 +66,7 @@ result<mapped_file_handle::size_type> mapped_file_handle::reserve(size_type rese
result<void> mapped_file_handle::close() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_mh.is_valid())
{
OUTCOME_TRYV(_mh.close());
@@ -79,7 +79,7 @@ result<void> mapped_file_handle::close() noexcept
}
native_handle_type mapped_file_handle::release() noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_mh.is_valid())
{
(void) _mh.close();
@@ -93,7 +93,7 @@ native_handle_type mapped_file_handle::release() noexcept
result<mapped_file_handle::extent_type> mapped_file_handle::truncate(extent_type newsize) noexcept
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
// Release all maps and sections and truncate the backing file to zero
if(newsize == 0)
{
@@ -108,9 +108,9 @@ result<mapped_file_handle::extent_type> mapped_file_handle::truncate(extent_type
OUTCOME_TRYV(reserve(_reservation));
return ret;
}
- // Ask the section what size it is. If multiple AFIO processes are using the same file,
+ // Ask the section what size it is. If multiple LLFIO processes are using the same file,
// because the section is a singleton based on the canonical path of the file, another
- // AFIO in another process may have already resized the section for us in which case
+ // LLFIO in another process may have already resized the section for us in which case
// we can skip doing work now.
OUTCOME_TRY(size, _sh.length());
if(size != newsize)
@@ -178,4 +178,4 @@ result<mapped_file_handle::extent_type> mapped_file_handle::update_map() noexcep
return length;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/path_discovery.ipp b/include/llfio/v2.0/detail/impl/windows/path_discovery.ipp
index 992992ed..cec17ddc 100644
--- a/include/afio/v2.0/detail/impl/windows/path_discovery.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/path_discovery.ipp
@@ -22,7 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_PATH_DISCOVERY_INCLUDING
+#ifndef LLFIO_PATH_DISCOVERY_INCLUDING
#error Must be included by ../path_discovery.ipp only
#endif
@@ -30,7 +30,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <ShlObj.h>
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace path_discovery
{
@@ -123,4 +123,4 @@ namespace path_discovery
}
} // namespace path_discovery
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/path_handle.ipp b/include/llfio/v2.0/detail/impl/windows/path_handle.ipp
index 218339ca..35c375ed 100644
--- a/include/afio/v2.0/detail/impl/windows/path_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/path_handle.ipp
@@ -25,7 +25,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../path_handle.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
result<path_handle> path_handle::path(const path_handle &base, path_handle::path_view_type path) noexcept
{
@@ -33,7 +33,7 @@ result<path_handle> path_handle::path(const path_handle &base, path_handle::path
using namespace windows_nt_kernel;
result<path_handle> ret{path_handle(native_handle_type())};
native_handle_type &nativeh = ret.value()._v;
- AFIO_LOG_FUNCTION_CALL(&ret);
+ LLFIO_LOG_FUNCTION_CALL(&ret);
nativeh.behaviour |= native_handle_type::disposition::directory;
DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
// Open directory with no access requested, this is much faster than asking for access
@@ -98,4 +98,4 @@ result<path_handle> path_handle::path(const path_handle &base, path_handle::path
return ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/path_view.ipp b/include/llfio/v2.0/detail/impl/windows/path_view.ipp
index 7439a020..a5ea3bc3 100644
--- a/include/afio/v2.0/detail/impl/windows/path_view.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/path_view.ipp
@@ -25,9 +25,9 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../path_view.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC void path_view::c_str::_from_utf8(const path_view &view) noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void path_view::c_str::_from_utf8(const path_view &view) noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
@@ -35,7 +35,7 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC void path_view::c_str::_from_utf8(const path_view
NTSTATUS ntstat = RtlUTF8ToUnicodeN(_buffer, static_cast<ULONG>(sizeof(_buffer) - sizeof(wchar_t)), &written, view._state._utf8.data(), static_cast<ULONG>(view._state._utf8.size()));
if(ntstat < 0)
{
- AFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str());
+ LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str());
abort();
}
length = static_cast<uint16_t>(written / sizeof(wchar_t));
@@ -52,4 +52,4 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC void path_view::c_str::_from_utf8(const path_view
buffer = _buffer;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/stat.ipp b/include/llfio/v2.0/detail/impl/windows/stat.ipp
index aa337be5..24e75c67 100644
--- a/include/afio/v2.0/detail/impl/windows/stat.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/stat.ipp
@@ -28,11 +28,11 @@ Distributed under the Boost Software License, Version 1.0.
#include <winioctl.h> // for DeviceIoControl codes
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat_t::want wanted) noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat_t::want wanted) noexcept
{
- AFIO_LOG_FUNCTION_CALL(&h);
+ LLFIO_LOG_FUNCTION_CALL(&h);
windows_nt_kernel::init();
using namespace windows_nt_kernel;
alignas(8) wchar_t buffer[32769];
@@ -221,4 +221,4 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> stat_t::fill(const handle &h, stat
return ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/statfs.ipp b/include/llfio/v2.0/detail/impl/windows/statfs.ipp
index 1bb85e26..4837986e 100644
--- a/include/afio/v2.0/detail/impl/windows/statfs.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/statfs.ipp
@@ -26,11 +26,11 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../statfs.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, statfs_t::want wanted) noexcept
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, statfs_t::want wanted) noexcept
{
- AFIO_LOG_FUNCTION_CALL(&h);
+ LLFIO_LOG_FUNCTION_CALL(&h);
windows_nt_kernel::init();
using namespace windows_nt_kernel;
alignas(8) wchar_t buffer[32769];
@@ -202,4 +202,4 @@ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> statfs_t::fill(const handle &h, st
return ret;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/storage_profile.ipp b/include/llfio/v2.0/detail/impl/windows/storage_profile.ipp
index 96b58814..d61ba046 100644
--- a/include/afio/v2.0/detail/impl/windows/storage_profile.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/storage_profile.ipp
@@ -31,7 +31,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <intrin.h> // for __cpuid
#endif
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace storage_profile
{
@@ -437,4 +437,4 @@ namespace storage_profile
} // namespace storage
} // namespace storage_profile
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/llfio/v2.0/detail/impl/windows/symlink_handle.ipp b/include/llfio/v2.0/detail/impl/windows/symlink_handle.ipp
new file mode 100644
index 00000000..63097a07
--- /dev/null
+++ b/include/llfio/v2.0/detail/impl/windows/symlink_handle.ipp
@@ -0,0 +1,283 @@
+/* A handle to a symbolic link
+(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
+File Created: Jul 2018
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "../../../symlink_handle.hpp"
+#include "import.hpp"
+
+LLFIO_V2_NAMESPACE_BEGIN
+
+result<symlink_handle> symlink_handle::clone(mode mode_, deadline /*unused*/) const noexcept
+{
+ LLFIO_LOG_FUNCTION_CALL(this);
+ result<symlink_handle> ret(symlink_handle(native_handle_type(), _devid, _inode, _flags));
+ OUTCOME_TRY(do_clone_handle(ret.value()._v, _v, mode_, caching::all, _flags));
+ return ret;
+}
+
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<symlink_handle> symlink_handle::symlink(const path_handle &base, symlink_handle::path_view_type path, symlink_handle::mode _mode, symlink_handle::creation _creation, flag flags) noexcept
+{
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ result<symlink_handle> ret(symlink_handle(native_handle_type(), 0, 0, flags));
+ native_handle_type &nativeh = ret.value()._v;
+ LLFIO_LOG_FUNCTION_CALL(&ret);
+ nativeh.behaviour |= native_handle_type::disposition::symlink;
+ DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ if(_mode == mode::append || _creation == creation::truncate)
+ {
+ return errc::function_not_supported;
+ }
+ OUTCOME_TRY(access, access_mask_from_handle_mode(nativeh, _mode, flags));
+ OUTCOME_TRY(attribs, attributes_from_handle_caching_and_flags(nativeh, caching::all, flags));
+ nativeh.behaviour &= ~native_handle_type::disposition::seekable; // not seekable
+ if(base.is_valid() || path.is_ntpath())
+ {
+ DWORD creatdisp = 0x00000001 /*FILE_OPEN*/;
+ switch(_creation)
+ {
+ case creation::open_existing:
+ break;
+ case creation::only_if_not_exist:
+ creatdisp = 0x00000002 /*FILE_CREATE*/;
+ break;
+ case creation::if_needed:
+ creatdisp = 0x00000003 /*FILE_OPEN_IF*/;
+ break;
+ case creation::truncate:
+ creatdisp = 0x00000004 /*FILE_OVERWRITE*/;
+ break;
+ }
+
+ attribs &= 0x00ffffff; // the real attributes only, not the win32 flags
+ OUTCOME_TRY(ntflags, ntflags_from_handle_caching_and_flags(nativeh, caching::all, flags));
+ ntflags |= 0x4000 /*FILE_OPEN_FOR_BACKUP_INTENT*/ | 0x00200000 /*FILE_OPEN_REPARSE_POINT*/;
+ ntflags |= 0x040 /*FILE_NON_DIRECTORY_FILE*/; // do not open a directory
+ IO_STATUS_BLOCK isb = make_iostatus();
+
+ path_view::c_str zpath(path, true);
+ UNICODE_STRING _path{};
+ _path.Buffer = const_cast<wchar_t *>(zpath.buffer);
+ _path.MaximumLength = (_path.Length = static_cast<USHORT>(zpath.length * sizeof(wchar_t))) + sizeof(wchar_t);
+ if(zpath.length >= 4 && _path.Buffer[0] == '\\' && _path.Buffer[1] == '!' && _path.Buffer[2] == '!' && _path.Buffer[3] == '\\')
+ {
+ _path.Buffer += 3;
+ _path.Length -= 3 * sizeof(wchar_t);
+ _path.MaximumLength -= 3 * sizeof(wchar_t);
+ }
+
+ OBJECT_ATTRIBUTES oa{};
+ memset(&oa, 0, sizeof(oa));
+ oa.Length = sizeof(OBJECT_ATTRIBUTES);
+ oa.ObjectName = &_path;
+ oa.RootDirectory = base.is_valid() ? base.native_handle().h : nullptr;
+ oa.Attributes = 0x40 /*OBJ_CASE_INSENSITIVE*/;
+ // if(!!(flags & file_flags::int_opening_link))
+ // oa.Attributes|=0x100/*OBJ_OPENLINK*/;
+
+ LARGE_INTEGER AllocationSize{};
+ memset(&AllocationSize, 0, sizeof(AllocationSize));
+ NTSTATUS ntstat = NtCreateFile(&nativeh.h, access, &oa, &isb, &AllocationSize, attribs, fileshare, creatdisp, ntflags, nullptr, 0);
+ if(STATUS_PENDING == ntstat)
+ {
+ ntstat = ntwait(nativeh.h, isb, deadline());
+ }
+ if(ntstat < 0)
+ {
+ return ntkernel_error(ntstat);
+ }
+ }
+ else
+ {
+ DWORD creation = OPEN_EXISTING;
+ switch(_creation)
+ {
+ case creation::open_existing:
+ break;
+ case creation::only_if_not_exist:
+ creation = CREATE_NEW;
+ break;
+ case creation::if_needed:
+ creation = OPEN_ALWAYS;
+ break;
+ case creation::truncate:
+ creation = TRUNCATE_EXISTING;
+ break;
+ }
+ // required to open a symlink
+ attribs |= FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
+ path_view::c_str zpath(path, false);
+ if(INVALID_HANDLE_VALUE == (nativeh.h = CreateFileW_(zpath.buffer, access, fileshare, nullptr, creation, attribs, nullptr))) // NOLINT
+ {
+ DWORD errcode = GetLastError();
+ // assert(false);
+ return win32_error(errcode);
+ }
+ }
+ return ret;
+}
+
+result<symlink_handle::buffers_type> symlink_handle::read(symlink_handle::io_request<symlink_handle::buffers_type> req) noexcept
+{
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ LLFIO_LOG_FUNCTION_CALL(this);
+ using windows_nt_kernel::REPARSE_DATA_BUFFER;
+ symlink_handle::buffers_type tofill;
+ if(req.kernelbuffer.empty())
+ {
+ // Let's assume the average symbolic link will be 256 characters long.
+ size_t toallocate = (sizeof(FILE_ID_FULL_DIR_INFORMATION) + 256 * sizeof(wchar_t));
+ auto *mem = new(std::nothrow) char[toallocate];
+ if(mem == nullptr)
+ {
+ return errc::not_enough_memory;
+ }
+ tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
+ tofill._kernel_buffer_size = toallocate;
+ }
+ REPARSE_DATA_BUFFER *rpd;
+ size_t bytes;
+ for(;;)
+ {
+ rpd = req.kernelbuffer.empty() ? reinterpret_cast<REPARSE_DATA_BUFFER *>(tofill._kernel_buffer.get()) : reinterpret_cast<REPARSE_DATA_BUFFER *>(req.kernelbuffer.data());
+ bytes = req.kernelbuffer.empty() ? static_cast<ULONG>(tofill._kernel_buffer_size) : static_cast<ULONG>(req.kernelbuffer.size());
+ DWORD written = 0;
+ if(!DeviceIoControl(_v.h, FSCTL_GET_REPARSE_POINT, NULL, 0, rpd, (DWORD) bytes, &written, NULL))
+ {
+ DWORD errcode = GetLastError();
+ if(req.kernelbuffer.empty() && (errcode == ERROR_INSUFFICIENT_BUFFER || errcode == ERROR_MORE_DATA))
+ {
+ tofill._kernel_buffer.reset();
+ size_t toallocate = tofill._kernel_buffer_size * 2;
+ auto *mem = new(std::nothrow) char[toallocate];
+ if(mem == nullptr)
+ {
+ return errc::not_enough_memory;
+ }
+ tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
+ tofill._kernel_buffer_size = toallocate;
+ continue;
+ }
+ return win32_error(errcode);
+ }
+ switch(rpd->ReparseTag)
+ {
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ tofill._link = path_view(rpd->MountPointReparseBuffer.PathBuffer + rpd->MountPointReparseBuffer.SubstituteNameOffset / sizeof(rpd->MountPointReparseBuffer.PathBuffer[0]), rpd->MountPointReparseBuffer.SubstituteNameLength / sizeof(rpd->MountPointReparseBuffer.PathBuffer[0]));
+ tofill._type = symlink_type::win_junction;
+ return std::move(tofill);
+ case IO_REPARSE_TAG_SYMLINK:
+ tofill._link = path_view(rpd->SymbolicLinkReparseBuffer.PathBuffer + rpd->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(rpd->SymbolicLinkReparseBuffer.PathBuffer[0]), rpd->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(rpd->SymbolicLinkReparseBuffer.PathBuffer[0]));
+ tofill._type = symlink_type::symbolic;
+ return std::move(tofill);
+ }
+ return errc::protocol_not_supported;
+ }
+}
+
+result<symlink_handle::const_buffers_type> symlink_handle::write(symlink_handle::io_request<symlink_handle::const_buffers_type> req, deadline /*unused*/) noexcept
+{
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ LLFIO_LOG_FUNCTION_CALL(this);
+ using windows_nt_kernel::REPARSE_DATA_BUFFER;
+ size_t destpathbytes = req.buffers.path().native_size() * sizeof(wchar_t);
+ size_t buffersize = sizeof(REPARSE_DATA_BUFFER) + destpathbytes * 2 + 256;
+ if(buffersize < req.kernelbuffer.size())
+ {
+ return errc::not_enough_memory;
+ }
+ const size_t headerlen = offsetof(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
+ auto *buffer = req.kernelbuffer.empty() ? alloca(buffersize) : req.kernelbuffer.data();
+ memset(buffer, 0, sizeof(REPARSE_DATA_BUFFER));
+ auto *rpd = (REPARSE_DATA_BUFFER *) buffer;
+ path_view::c_str zpath(req.buffers.path(), true);
+ switch(req.buffers.type())
+ {
+ case symlink_type::none:
+ return errc::invalid_argument;
+ case symlink_type::symbolic:
+ {
+ const size_t reparsebufferheaderlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - headerlen;
+ rpd->ReparseTag = IO_REPARSE_TAG_SYMLINK;
+ if(zpath.length >= 4 && zpath.buffer[0] == '\\' && zpath.buffer[1] == '!' && zpath.buffer[2] == '!' && zpath.buffer[3] == '\\')
+ {
+ memcpy(rpd->SymbolicLinkReparseBuffer.PathBuffer, zpath.buffer + 3, destpathbytes - 6 + sizeof(wchar_t));
+ rpd->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
+ rpd->SymbolicLinkReparseBuffer.SubstituteNameLength = (USHORT) destpathbytes - 6;
+ rpd->SymbolicLinkReparseBuffer.PrintNameOffset = (USHORT)(destpathbytes - 6 + sizeof(wchar_t));
+ rpd->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT) destpathbytes - 6;
+ memcpy(rpd->SymbolicLinkReparseBuffer.PathBuffer + rpd->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t), zpath.buffer + 3, rpd->SymbolicLinkReparseBuffer.PrintNameLength - 6 + sizeof(wchar_t));
+ }
+ else
+ {
+ memcpy(rpd->SymbolicLinkReparseBuffer.PathBuffer, zpath.buffer, destpathbytes + sizeof(wchar_t));
+ rpd->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
+ rpd->SymbolicLinkReparseBuffer.SubstituteNameLength = (USHORT) destpathbytes;
+ rpd->SymbolicLinkReparseBuffer.PrintNameOffset = (USHORT)(destpathbytes + sizeof(wchar_t));
+ rpd->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT) destpathbytes;
+ memcpy(rpd->SymbolicLinkReparseBuffer.PathBuffer + rpd->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t), zpath.buffer, rpd->SymbolicLinkReparseBuffer.PrintNameLength + sizeof(wchar_t));
+ }
+ rpd->SymbolicLinkReparseBuffer.Flags = req.buffers.path().is_relative() ? 0x1 /*SYMLINK_FLAG_RELATIVE*/ : 0;
+ rpd->ReparseDataLength = (USHORT)(rpd->SymbolicLinkReparseBuffer.SubstituteNameLength + rpd->SymbolicLinkReparseBuffer.PrintNameLength + 2 * sizeof(wchar_t) + reparsebufferheaderlen);
+ break;
+ }
+ case symlink_type::win_wsl:
+ // TODO FIXME
+ abort();
+ case symlink_type::win_junction:
+ {
+ const size_t reparsebufferheaderlen = offsetof(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - headerlen;
+ rpd->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ if(zpath.length >= 4 && zpath.buffer[0] == '\\' && zpath.buffer[1] == '!' && zpath.buffer[2] == '!' && zpath.buffer[3] == '\\')
+ {
+ memcpy(rpd->MountPointReparseBuffer.PathBuffer, zpath.buffer + 3, destpathbytes - 6 + sizeof(wchar_t));
+ rpd->MountPointReparseBuffer.SubstituteNameOffset = 0;
+ rpd->MountPointReparseBuffer.SubstituteNameLength = (USHORT) destpathbytes - 6;
+ rpd->MountPointReparseBuffer.PrintNameOffset = (USHORT)(destpathbytes - 6 + sizeof(wchar_t));
+ rpd->MountPointReparseBuffer.PrintNameLength = (USHORT) destpathbytes - 6;
+ memcpy(rpd->MountPointReparseBuffer.PathBuffer + rpd->MountPointReparseBuffer.PrintNameOffset / sizeof(wchar_t), zpath.buffer + 3, rpd->MountPointReparseBuffer.PrintNameLength - 6 + sizeof(wchar_t));
+ }
+ else
+ {
+ memcpy(rpd->MountPointReparseBuffer.PathBuffer, zpath.buffer, destpathbytes + sizeof(wchar_t));
+ rpd->MountPointReparseBuffer.SubstituteNameOffset = 0;
+ rpd->MountPointReparseBuffer.SubstituteNameLength = (USHORT) destpathbytes;
+ rpd->MountPointReparseBuffer.PrintNameOffset = (USHORT)(destpathbytes + sizeof(wchar_t));
+ rpd->MountPointReparseBuffer.PrintNameLength = (USHORT) destpathbytes;
+ memcpy(rpd->MountPointReparseBuffer.PathBuffer + rpd->MountPointReparseBuffer.PrintNameOffset / sizeof(wchar_t), zpath.buffer, rpd->MountPointReparseBuffer.PrintNameLength + sizeof(wchar_t));
+ }
+ rpd->ReparseDataLength = (USHORT)(rpd->MountPointReparseBuffer.SubstituteNameLength + rpd->MountPointReparseBuffer.PrintNameLength + 2 * sizeof(wchar_t) + reparsebufferheaderlen);
+ break;
+ }
+ }
+ DWORD bytesout = 0;
+ if(DeviceIoControl(_v.h, FSCTL_SET_REPARSE_POINT, rpd, (DWORD)(rpd->ReparseDataLength + headerlen), NULL, 0, &bytesout, NULL) == 0)
+ {
+ return win32_error();
+ }
+ return success(std::move(req.buffers));
+}
+
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/utils.ipp b/include/llfio/v2.0/detail/impl/windows/utils.ipp
index c6792acd..f483b5ea 100644
--- a/include/afio/v2.0/detail/impl/windows/utils.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/utils.ipp
@@ -27,14 +27,14 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../quickcpplib/include/spinlock.hpp"
#include "import.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace utils
{
// Stupid MSVC ...
namespace detail
{
- using namespace AFIO_V2_NAMESPACE::detail;
+ using namespace LLFIO_V2_NAMESPACE::detail;
}
size_t page_size() noexcept
{
@@ -102,7 +102,7 @@ namespace utils
using namespace windows_nt_kernel;
if(RtlGenRandom(buffer, static_cast<ULONG>(bytes)) == 0u)
{
- AFIO_LOG_FATAL(0, "afio: Kernel crypto function failed");
+ LLFIO_LOG_FATAL(0, "llfio: Kernel crypto function failed");
std::terminate();
}
}
@@ -218,7 +218,7 @@ namespace utils
#ifndef NDEBUG
else if(ret.page_size_used > 65536)
{
- printf("afio: Large page allocation successful\n");
+ printf("llfio: Large page allocation successful\n");
}
#endif
return ret;
@@ -228,11 +228,11 @@ namespace utils
(void) bytes;
if(VirtualFree(p, 0, MEM_RELEASE) == 0)
{
- AFIO_LOG_FATAL(p, "afio: Freeing large pages failed");
+ LLFIO_LOG_FATAL(p, "llfio: Freeing large pages failed");
std::terminate();
}
}
} // namespace detail
} // namespace utils
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/directory_handle.hpp b/include/llfio/v2.0/directory_handle.hpp
index cbb37f5d..8c5aa09d 100644
--- a/include/afio/v2.0/directory_handle.hpp
+++ b/include/llfio/v2.0/directory_handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_DIRECTORY_HANDLE_H
-#define AFIO_DIRECTORY_HANDLE_H
+#ifndef LLFIO_DIRECTORY_HANDLE_H
+#define LLFIO_DIRECTORY_HANDLE_H
#include "path_discovery.hpp"
#include "stat.hpp"
@@ -37,7 +37,7 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
struct directory_entry
{
@@ -61,9 +61,9 @@ static_assert(std::is_standard_layout<directory_entry>::value, "directory_entry
/*! \class directory_handle
\brief A handle to a directory which can be enumerated.
*/
-class AFIO_DECL directory_handle : public path_handle, public fs_handle
+class LLFIO_DECL directory_handle : public path_handle, public fs_handle
{
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept final { return *this; }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept final { return *this; }
public:
using path_type = path_handle::path_type;
@@ -123,7 +123,7 @@ public:
enum class filter
{
none, //!< Do no filtering at all
- fastdeleted //!< Filter out AFIO deleted files based on their filename (fast and fairly reliable)
+ fastdeleted //!< Filter out LLFIO deleted files based on their filename (fast and fairly reliable)
};
public:
@@ -151,7 +151,7 @@ public:
//! No copy assignment
directory_handle &operator=(const directory_handle &) = delete;
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(directory_handle &o) noexcept
{
directory_handle temp(std::move(*this));
@@ -163,15 +163,15 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<directory_handle> directory(const path_handle &base, path_view_type path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<directory_handle> directory(const path_handle &base, path_view_type path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept;
/*! Create a directory handle creating a randomly named file on a path.
The file is opened exclusively with `creation::only_if_not_exist` so it
will never collide with nor overwrite any existing entry.
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<directory_handle> random_directory(const path_handle &dirpath, mode _mode = mode::write, caching _caching = caching::temporary, flag flags = flag::none) noexcept
{
try
@@ -199,23 +199,23 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<directory_handle> temp_directory(path_view_type name = path_view_type(), mode _mode = mode::write, creation _creation = creation::if_needed, caching _caching = caching::all, flag flags = flag::none) noexcept
{
auto &tempdirh = path_discovery::storage_backed_temporary_files_directory();
return name.empty() ? random_directory(tempdirh, _mode, _caching, flags) : directory(tempdirh, name, _mode, _creation, _caching, flags);
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~directory_handle() override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~directory_handle() override
{
if(_v)
{
(void) directory_handle::close();
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_flags & flag::unlink_on_first_close)
{
auto ret = unlink();
@@ -242,7 +242,7 @@ public:
\mallocs On POSIX if changing the mode, we must loop calling `current_path()` and
trying to open the path returned. Thus many allocations may occur.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<directory_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<directory_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept;
/*! Return a copy of this directory handle, but as a path handle.
@@ -250,12 +250,12 @@ public:
\mallocs On POSIX, we must loop calling `current_path()` and
trying to open the path returned. Thus many allocations may occur.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> clone_to_path_handle() const noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> clone_to_path_handle() const noexcept;
#ifdef _WIN32
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
result<void> relink(const path_handle &base, path_view_type newpath, bool atomic_replace = true, deadline d = std::chrono::seconds(30)) noexcept override;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
result<void> unlink(deadline d = std::chrono::seconds(30)) noexcept override;
#endif
@@ -283,21 +283,21 @@ public:
\mallocs If the `kernelbuffer` parameter is set on entry, no memory allocations.
If unset, at least one memory allocation, possibly more is performed.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<enumerate_info> enumerate(buffers_type &&tofill, path_view_type glob = path_view_type(), filter filtering = filter::fastdeleted, span<char> kernelbuffer = span<char>()) const noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<enumerate_info> enumerate(buffers_type &&tofill, path_view_type glob = path_view_type(), filter filtering = filter::fastdeleted, span<char> kernelbuffer = span<char>()) const noexcept;
};
inline std::ostream &operator<<(std::ostream &s, const directory_handle::filter &v)
{
static constexpr const char *values[] = {"none", "fastdeleted"};
if(static_cast<size_t>(v) >= sizeof(values) / sizeof(values[0]) || (values[static_cast<size_t>(v)] == nullptr))
{
- return s << "afio::directory_handle::filter::<unknown>";
+ return s << "llfio::directory_handle::filter::<unknown>";
}
- return s << "afio::directory_handle::filter::" << values[static_cast<size_t>(v)];
+ return s << "llfio::directory_handle::filter::" << values[static_cast<size_t>(v)];
}
inline std::ostream &operator<<(std::ostream &s, const directory_handle::enumerate_info & /*unused*/)
{
- return s << "afio::directory_handle::enumerate_info";
+ return s << "llfio::directory_handle::enumerate_info";
}
//! \brief Constructor for `directory_handle`
@@ -322,7 +322,8 @@ inline void swap(directory_handle &self, directory_handle &o) noexcept
\errors Any of the values POSIX open() or CreateFile() can return.
*/
-inline result<directory_handle> directory(const path_handle &base, directory_handle::path_view_type path, directory_handle::mode _mode = directory_handle::mode::read, directory_handle::creation _creation = directory_handle::creation::open_existing, directory_handle::caching _caching = directory_handle::caching::all, directory_handle::flag flags = directory_handle::flag::none) noexcept
+inline result<directory_handle> directory(const path_handle &base, directory_handle::path_view_type path, directory_handle::mode _mode = directory_handle::mode::read, directory_handle::creation _creation = directory_handle::creation::open_existing, directory_handle::caching _caching = directory_handle::caching::all,
+ directory_handle::flag flags = directory_handle::flag::none) noexcept
{
return directory_handle::directory(std::forward<decltype(base)>(base), std::forward<decltype(path)>(path), std::forward<decltype(_mode)>(_mode), std::forward<decltype(_creation)>(_creation), std::forward<decltype(_caching)>(_caching), std::forward<decltype(flags)>(flags));
}
@@ -344,7 +345,8 @@ parameter is ignored.
\errors Any of the values POSIX open() or CreateFile() can return.
*/
-inline result<directory_handle> temp_directory(directory_handle::path_view_type name = directory_handle::path_view_type(), directory_handle::mode _mode = directory_handle::mode::write, directory_handle::creation _creation = directory_handle::creation::if_needed, directory_handle::caching _caching = directory_handle::caching::all, directory_handle::flag flags = directory_handle::flag::none) noexcept
+inline result<directory_handle> temp_directory(directory_handle::path_view_type name = directory_handle::path_view_type(), directory_handle::mode _mode = directory_handle::mode::write, directory_handle::creation _creation = directory_handle::creation::if_needed,
+ directory_handle::caching _caching = directory_handle::caching::all, directory_handle::flag flags = directory_handle::flag::none) noexcept
{
return directory_handle::temp_directory(std::forward<decltype(name)>(name), std::forward<decltype(_mode)>(_mode), std::forward<decltype(_creation)>(_creation), std::forward<decltype(_caching)>(_caching), std::forward<decltype(flags)>(flags));
}
@@ -363,22 +365,23 @@ is no longer using any items within (leafnames are views onto the original kerne
\mallocs If the `kernelbuffer` parameter is set on entry, no memory allocations.
If unset, at least one memory allocation, possibly more is performed.
*/
-inline result<directory_handle::enumerate_info> enumerate(const directory_handle &self, directory_handle::buffers_type &&tofill, directory_handle::path_view_type glob = directory_handle::path_view_type(), directory_handle::filter filtering = directory_handle::filter::fastdeleted, span<char> kernelbuffer = span<char>()) noexcept
+inline result<directory_handle::enumerate_info> enumerate(const directory_handle &self, directory_handle::buffers_type &&tofill, directory_handle::path_view_type glob = directory_handle::path_view_type(), directory_handle::filter filtering = directory_handle::filter::fastdeleted,
+ span<char> kernelbuffer = span<char>()) noexcept
{
return self.enumerate(std::forward<decltype(tofill)>(tofill), std::forward<decltype(glob)>(glob), std::forward<decltype(filtering)>(filtering), std::forward<decltype(kernelbuffer)>(kernelbuffer));
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/directory_handle.ipp"
#else
#include "detail/impl/posix/directory_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/file_handle.hpp b/include/llfio/v2.0/file_handle.hpp
index 04634ed5..de8386f0 100644
--- a/include/afio/v2.0/file_handle.hpp
+++ b/include/llfio/v2.0/file_handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_FILE_HANDLE_H
-#define AFIO_FILE_HANDLE_H
+#ifndef LLFIO_FILE_HANDLE_H
+#define LLFIO_FILE_HANDLE_H
#include "io_handle.hpp"
#include "path_discovery.hpp"
@@ -36,7 +36,7 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
class io_service;
@@ -52,9 +52,9 @@ async_file_handle.
</table>
*/
-class AFIO_DECL file_handle : public io_handle, public fs_handle
+class LLFIO_DECL file_handle : public io_handle, public fs_handle
{
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept final { return *this; }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept final { return *this; }
public:
using path_type = io_handle::path_type;
@@ -103,7 +103,7 @@ public:
return *this;
}
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(file_handle &o) noexcept
{
file_handle temp(std::move(*this));
@@ -121,8 +121,8 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<file_handle> file(const path_handle &base, path_view_type path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<file_handle> file(const path_handle &base, path_view_type path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept;
/*! Create a file handle creating a randomly named file on a path.
The file is opened exclusively with `creation::only_if_not_exist` so it
will never collide with nor overwrite any existing file. Note also
@@ -131,7 +131,7 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<file_handle> random_file(const path_handle &dirpath, mode _mode = mode::write, caching _caching = caching::temporary, flag flags = flag::none) noexcept
{
try
@@ -167,7 +167,7 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<file_handle> temp_file(path_view_type name = path_view_type(), mode _mode = mode::write, creation _creation = creation::if_needed, caching _caching = caching::temporary, flag flags = flag::unlink_on_first_close) noexcept
{
auto &tempdirh = path_discovery::storage_backed_temporary_files_directory();
@@ -183,19 +183,19 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<file_handle> temp_inode(const path_handle &dirh = path_discovery::storage_backed_temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<file_handle> temp_inode(const path_handle &dirh = path_discovery::storage_backed_temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~file_handle() override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~file_handle() override
{
if(_v)
{
(void) file_handle::close();
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
{
- AFIO_LOG_FUNCTION_CALL(this);
+ LLFIO_LOG_FUNCTION_CALL(this);
if(_flags & flag::unlink_on_first_close)
{
auto ret = unlink();
@@ -208,10 +208,17 @@ public:
}
}
}
+#ifndef NDEBUG
+ if(_v)
+ {
+ // Tell handle::close() that we have correctly executed
+ _v.behaviour |= native_handle_type::disposition::_child_close_executed;
+ }
+#endif
return io_handle::close();
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
/*! Clone this handle (copy constructor is disabled to avoid accidental copying),
optionally race free reopening the handle with different access or caching.
@@ -225,7 +232,7 @@ public:
\mallocs On POSIX if changing the mode, we must loop calling `current_path()` and
trying to open the path returned. Thus many allocations may occur.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept;
//! The i/o service this handle is attached to, if any
io_service *service() const noexcept { return _service; }
@@ -234,8 +241,8 @@ public:
\errors Any of the values POSIX fstat() or GetFileInformationByHandleEx() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> maximum_extent() const noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> maximum_extent() const noexcept;
/*! Resize the current maximum permitted extent of the file to the given extent, avoiding any
new allocation of physical storage where supported. Note that on extents based filing systems
@@ -245,16 +252,16 @@ public:
\param newsize The bytes to truncate the file to.
\errors Any of the values POSIX ftruncate() or SetFileInformationByHandle() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> truncate(extent_type newsize) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> truncate(extent_type newsize) noexcept;
/*! \brief Returns a list of currently valid extents for this open file. WARNING: racy!
\return A vector of pairs of extent offset + extent length representing the valid extents
in this file. Filing systems which do not support extents return a single extent matching
the length of the file rather than returning an error.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<std::vector<std::pair<extent_type, extent_type>>> extents() const noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<std::vector<std::pair<extent_type, extent_type>>> extents() const noexcept;
/*! \brief Efficiently zero, and possibly deallocate, data on storage.
@@ -275,8 +282,8 @@ public:
\mallocs The default synchronous implementation in file_handle performs no memory allocation.
The asynchronous implementation in async_file_handle may perform one calloc and one free.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> zero(extent_type offset, extent_type bytes, deadline d = deadline()) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> zero(extent_type offset, extent_type bytes, deadline d = deadline()) noexcept;
};
//! \brief Constructor for `file_handle`
@@ -411,23 +418,23 @@ inline result<file_handle::extent_type> zero(file_handle &self, file_handle::ext
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/file_handle.ipp"
#else
#include "detail/impl/posix/file_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
// Needs to be here as path discovery uses file_handle
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#include "detail/impl/path_discovery.ipp"
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/fs_handle.hpp b/include/llfio/v2.0/fs_handle.hpp
index 91d45e44..ed4ef1f2 100644
--- a/include/afio/v2.0/fs_handle.hpp
+++ b/include/llfio/v2.0/fs_handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_FS_HANDLE_H
-#define AFIO_FS_HANDLE_H
+#ifndef LLFIO_FS_HANDLE_H
+#define LLFIO_FS_HANDLE_H
#include "path_handle.hpp"
#include "path_view.hpp"
@@ -37,14 +37,14 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
/*! \class fs_handle
\brief A handle to something with a device and inode number.
\sa `algorithm::cached_parent_handle_adapter<T>`
*/
-class AFIO_DECL fs_handle
+class LLFIO_DECL fs_handle
{
public:
using dev_t = uint64_t;
@@ -59,7 +59,7 @@ protected:
mutable ino_t _inode{0};
//! Fill in _devid and _inode from the handle via fstat()
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<void> _fetch_inode() const noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<void> _fetch_inode() const noexcept;
virtual const handle &_get_handle() const noexcept = 0;
@@ -139,7 +139,7 @@ public:
\sa `algorithm::cached_parent_handle_adapter<T>` which overrides this with a zero cost
implementation, thus making unlinking and relinking very considerably quicker.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_handle> parent_path_handle(deadline d = std::chrono::seconds(30)) const noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_handle> parent_path_handle(deadline d = std::chrono::seconds(30)) const noexcept;
/*! Relinks the current path of this open handle to the new path specified. If `atomic_replace` is
true, the relink \b atomically and silently replaces any item at the new path specified. This operation
@@ -164,8 +164,8 @@ public:
\mallocs Except on platforms with race free syscalls for renaming open handles (Windows), calls
`current_path()` via `parent_path_handle()` and thus is both expensive and calls malloc many times.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
result<void> relink(const path_handle &base, path_view_type path, bool atomic_replace = true, deadline d = std::chrono::seconds(30)) noexcept;
/*! Unlinks the current path of this open handle, causing its entry to immediately disappear from the filing system.
@@ -190,11 +190,16 @@ public:
`current_path()` and thus is both expensive and calls malloc many times. On Windows, also calls
`current_path()` if `flag::disable_safety_unlinks` is not set.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
result<void> unlink(deadline d = std::chrono::seconds(30)) noexcept;
};
+namespace detail
+{
+ extern LLFIO_DECL result<path_handle> containing_directory(optional<std::reference_wrapper<filesystem::path>> out_filename, const handle &h, const fs_handle &fsh, deadline d) noexcept;
+}
+
// BEGIN make_free_functions.py
/*! Relinks the current path of this open handle to the new path specified. If `atomic_replace` is
true, the relink \b atomically and silently replaces any item at the new path specified. This operation
@@ -253,16 +258,16 @@ inline result<void> unlink(fs_handle &self, deadline d = std::chrono::seconds(30
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/fs_handle.ipp"
#else
#include "detail/impl/posix/fs_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/handle.hpp b/include/llfio/v2.0/handle.hpp
index 57f7618f..430848c7 100644
--- a/include/afio/v2.0/handle.hpp
+++ b/include/llfio/v2.0/handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_HANDLE_H
-#define AFIO_HANDLE_H
+#ifndef LLFIO_HANDLE_H
+#define LLFIO_HANDLE_H
#include "deadline.h"
#include "native_handle_type.hpp"
@@ -39,14 +39,14 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
class fs_handle;
/*! \class handle
\brief A native_handle_type which is managed by the lifetime of this object instance.
*/
-class AFIO_DECL handle
+class LLFIO_DECL handle
{
friend class fs_handle;
friend inline std::ostream &operator<<(std::ostream &s, const handle &v);
@@ -103,14 +103,14 @@ public:
editions of Windows, the file entry does not disappears but becomes unavailable for
anyone else to open with an `errc::resource_unavailable_try_again` error return. Because this is confusing, unless the
`win_disable_unlink_emulation` flag is also specified, this POSIX behaviour is
- somewhat emulated by AFIO on older Windows by renaming the file to a random name on `close()`
+ somewhat emulated by LLFIO on older Windows by renaming the file to a random name on `close()`
causing it to appear to have been unlinked immediately.
*/
unlink_on_first_close = 1U << 0U,
/*! Some kernel caching modes have unhelpfully inconsistent behaviours
in getting your data onto storage, so by default unless this flag is
- specified AFIO adds extra fsyncs to the following operations for the
+ specified LLFIO adds extra fsyncs to the following operations for the
caching modes specified below:
* truncation of file length either explicitly or during file open.
* closing of the handle either explicitly or in the destructor.
@@ -156,7 +156,7 @@ public:
created files on NTFS, unlike in almost every other major filing system. You have to
explicitly "opt in" to extents-based storage.
- As extents-based storage is nearly cost free on NTFS, AFIO by default opts in to
+ As extents-based storage is nearly cost free on NTFS, LLFIO by default opts in to
extents-based storage for any empty file it creates. If you don't want this, you
can specify this flag to prevent that happening.
*/
@@ -180,7 +180,7 @@ public:
constexpr handle() {} // NOLINT
//! Construct a handle from a supplied native handle
explicit constexpr handle(native_handle_type h, caching caching = caching::none, flag flags = flag::none) noexcept : _caching(caching), _flags(flags), _v(std::move(h)) {}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~handle();
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~handle();
//! No copy construction (use clone())
handle(const handle &) = delete;
//! No copy assignment
@@ -200,7 +200,7 @@ public:
return *this;
}
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(handle &o) noexcept
{
handle temp(std::move(*this));
@@ -217,18 +217,18 @@ public:
circumstances e.g. renaming may switch to a different hard link's path which is almost
certainly a bug.
- If AFIO was not able to determine the current path for this open handle e.g. the inode
+ If LLFIO was not able to determine the current path for this open handle e.g. the inode
has been unlinked, it returns an empty path. Be aware that FreeBSD can return an empty
- (deleted) path for file inodes no longer cached by the kernel path cache, AFIO cannot
+ (deleted) path for file inodes no longer cached by the kernel path cache, LLFIO cannot
detect the difference. FreeBSD will also return any path leading to the inode if it is
hard linked. FreeBSD does implement path retrieval for directory inodes
correctly however, and see `algorithm::stablized_path<T>` for a handle adapter which
makes use of that.
- On Linux if `/proc` is not mounted, this call fails with an error. All APIs in AFIO
+ On Linux if `/proc` is not mounted, this call fails with an error. All APIs in LLFIO
which require the use of `current_path()` can be told to not use it e.g. `flag::disable_safety_unlinks`.
It is up to you to detect if `current_path()` is not working, and to change how you
- call AFIO appropriately.
+ call LLFIO appropriately.
\warning This call is expensive, it always asks the kernel for the current path, and no
checking is done to ensure what the kernel returns is accurate or even sensible.
@@ -245,17 +245,17 @@ public:
taking advantage of directory inodes not having the same instability problems on any
platform.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_type> current_path() const noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_type> current_path() const noexcept;
//! Immediately close the native handle type managed by this handle
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept;
/*! Clone this handle (copy constructor is disabled to avoid accidental copying)
\errors Any of the values POSIX dup() or DuplicateHandle() can return.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<handle> clone() const noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<handle> clone() const noexcept;
//! Release the native handle type managed by this handle
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept
{
native_handle_type ret(std::move(_v));
return ret;
@@ -280,7 +280,7 @@ public:
\errors Whatever POSIX fcntl() returns. On Windows nothing is changed on the handle.
\mallocs No memory allocation.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> set_append_only(bool enable) noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> set_append_only(bool enable) noexcept;
//! True if overlapped
bool is_overlapped() const noexcept { return _v.is_overlapped(); }
@@ -322,36 +322,36 @@ inline std::ostream &operator<<(std::ostream &s, const handle &v)
{
auto _currentpath = v.current_path();
std::string currentpath = !_currentpath ? std::string(_currentpath.error().message().c_str()) : _currentpath.value().u8string();
- return s << "afio::handle(" << v._v._init << ", " << currentpath << ")";
+ return s << "llfio::handle(" << v._v._init << ", " << currentpath << ")";
}
- return s << "afio::handle(closed)";
+ return s << "llfio::handle(closed)";
}
inline std::ostream &operator<<(std::ostream &s, const handle::mode &v)
{
static constexpr const char *values[] = {"unchanged", nullptr, "none", nullptr, "attr_read", "attr_write", "read", "write", nullptr, "append"};
if(static_cast<size_t>(v) >= sizeof(values) / sizeof(values[0]) || (values[static_cast<size_t>(v)] == nullptr)) // NOLINT
{
- return s << "afio::handle::mode::<unknown>";
+ return s << "llfio::handle::mode::<unknown>";
}
- return s << "afio::handle::mode::" << values[static_cast<size_t>(v)]; // NOLINT
+ return s << "llfio::handle::mode::" << values[static_cast<size_t>(v)]; // NOLINT
}
inline std::ostream &operator<<(std::ostream &s, const handle::creation &v)
{
static constexpr const char *values[] = {"open_existing", "only_if_not_exist", "if_needed", "truncate"};
if(static_cast<size_t>(v) >= sizeof(values) / sizeof(values[0]) || (values[static_cast<size_t>(v)] == nullptr)) // NOLINT
{
- return s << "afio::handle::creation::<unknown>";
+ return s << "llfio::handle::creation::<unknown>";
}
- return s << "afio::handle::creation::" << values[static_cast<size_t>(v)]; // NOLINT
+ return s << "llfio::handle::creation::" << values[static_cast<size_t>(v)]; // NOLINT
}
inline std::ostream &operator<<(std::ostream &s, const handle::caching &v)
{
static constexpr const char *values[] = {"unchanged", "none", "only_metadata", "reads", "all", "reads_and_metadata", "temporary", "safety_fsyncs"};
if(static_cast<size_t>(v) >= sizeof(values) / sizeof(values[0]) || (values[static_cast<size_t>(v)] == nullptr)) // NOLINT
{
- return s << "afio::handle::caching::<unknown>";
+ return s << "llfio::handle::caching::<unknown>";
}
- return s << "afio::handle::caching::" << values[static_cast<size_t>(v)]; // NOLINT
+ return s << "llfio::handle::caching::" << values[static_cast<size_t>(v)]; // NOLINT
}
inline std::ostream &operator<<(std::ostream &s, const handle::flag &v)
{
@@ -404,7 +404,7 @@ inline std::ostream &operator<<(std::ostream &s, const handle::flag &v)
{
temp = "none";
}
- return s << "afio::handle::flag::" << temp;
+ return s << "llfio::handle::flag::" << temp;
}
/*! \brief Metaprogramming shim for constructing any `handle` subclass.
@@ -422,7 +422,7 @@ template <class T> struct construct
result<T> operator()() const noexcept { static_assert(!std::is_same<T, T>::value, "construct<T>() was not specialised for the type T supplied"); }
};
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
namespace detail
{
template <class Dest, class Src> inline void fill_failure_info(Dest &dest, const Src &src)
@@ -455,7 +455,7 @@ namespace detail
dest._tls_path_id2 = dest._tls_path_id1 - 17; // guaranteed invalid
}
}
-#if AFIO_LOGGING_LEVEL >= 2
+#if LLFIO_LOGGING_LEVEL >= 2
if(log().log_level() >= log_level::error)
{
dest._log_id = log().emplace_back(log_level::error, src.message().c_str(), static_cast<uint32_t>(nativeh._init), tls.this_thread_id);
@@ -466,14 +466,14 @@ namespace detail
}
#endif
-#if AFIO_EXPERIMENTAL_STATUS_CODE
+#if LLFIO_EXPERIMENTAL_STATUS_CODE
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
//! Helper for constructing an error code from an errc
-inline error_code generic_error(errc c)
+inline file_io_error generic_error(errc c)
{
- SYSTEM_ERROR2_NAMESPACE::status_code<error_domain<SYSTEM_ERROR2_NAMESPACE::generic_code::domain_type>> sc(c);
+ SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain<SYSTEM_ERROR2_NAMESPACE::generic_code::domain_type>> sc(c);
if(sc.failure())
{
detail::fill_failure_info(sc.value(), sc);
@@ -482,9 +482,9 @@ inline error_code generic_error(errc c)
}
#ifndef _WIN32
//! Helper for constructing an error code from a POSIX errno
-inline error_code posix_error(int c)
+inline file_io_error posix_error(int c)
{
- SYSTEM_ERROR2_NAMESPACE::status_code<error_domain<SYSTEM_ERROR2_NAMESPACE::posix_code::domain_type>> sc(c);
+ SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain<SYSTEM_ERROR2_NAMESPACE::posix_code::domain_type>> sc(c);
if(sc.failure())
{
detail::fill_failure_info(sc.value(), sc);
@@ -493,9 +493,9 @@ inline error_code posix_error(int c)
}
#else
//! Helper for constructing an error code from a DWORD
-inline error_code win32_error(SYSTEM_ERROR2_NAMESPACE::win32::DWORD c)
+inline file_io_error win32_error(SYSTEM_ERROR2_NAMESPACE::win32::DWORD c)
{
- SYSTEM_ERROR2_NAMESPACE::status_code<error_domain<SYSTEM_ERROR2_NAMESPACE::win32_code::domain_type>> sc(c);
+ SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain<SYSTEM_ERROR2_NAMESPACE::win32_code::domain_type>> sc(c);
if(sc.failure())
{
detail::fill_failure_info(sc.value(), sc);
@@ -503,9 +503,9 @@ inline error_code win32_error(SYSTEM_ERROR2_NAMESPACE::win32::DWORD c)
return sc;
}
//! Helper for constructing an error code from a NTSTATUS
-inline error_code ntkernel_error(SYSTEM_ERROR2_NAMESPACE::win32::NTSTATUS c)
+inline file_io_error ntkernel_error(SYSTEM_ERROR2_NAMESPACE::win32::NTSTATUS c)
{
- SYSTEM_ERROR2_NAMESPACE::status_code<error_domain<SYSTEM_ERROR2_NAMESPACE::nt_code::domain_type>> sc(c);
+ SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain<SYSTEM_ERROR2_NAMESPACE::nt_code::domain_type>> sc(c);
if(sc.failure())
{
detail::fill_failure_info(sc.value(), sc);
@@ -516,7 +516,7 @@ inline error_code ntkernel_error(SYSTEM_ERROR2_NAMESPACE::win32::NTSTATUS c)
#endif
-#else // AFIO_EXPERIMENTAL_STATUS_CODE
+#else // LLFIO_EXPERIMENTAL_STATUS_CODE
// failure_info is defined in config.hpp, this is its constructor which needs
// to be defined here so that we have handle's definition available
@@ -524,14 +524,14 @@ inline error_info::error_info(std::error_code _ec)
: ec(_ec)
{
// Here is a VERY useful place to breakpoint!
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
if(ec)
{
detail::fill_failure_info(*this, this->ec);
}
#endif
}
-#endif // AFIO_EXPERIMENTAL_STATUS_CODE
+#endif // LLFIO_EXPERIMENTAL_STATUS_CODE
// Define how we log handles and subclasses thereof
namespace detail
@@ -540,7 +540,7 @@ namespace detail
{
(void) inst;
(void) buffer;
- AFIO_LOG_INFO(inst->native_handle()._init, buffer);
+ LLFIO_LOG_INFO(inst->native_handle()._init, buffer);
}
}
@@ -557,16 +557,16 @@ inline result<void> close(handle &self) noexcept
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/handle.ipp"
#else
#include "detail/impl/posix/handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/io_handle.hpp b/include/llfio/v2.0/io_handle.hpp
index 2ada9efa..55aa1f21 100644
--- a/include/afio/v2.0/io_handle.hpp
+++ b/include/llfio/v2.0/io_handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_IO_HANDLE_H
-#define AFIO_IO_HANDLE_H
+#ifndef LLFIO_IO_HANDLE_H
+#define LLFIO_IO_HANDLE_H
#include "handle.hpp"
@@ -34,12 +34,12 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
/*! \class io_handle
\brief A handle to something capable of scatter-gather i/o.
*/
-class AFIO_DECL io_handle : public handle
+class LLFIO_DECL io_handle : public handle
{
public:
using path_type = handle::path_type;
@@ -51,10 +51,13 @@ public:
using flag = handle::flag;
//! The scatter buffer type used by this handle. Guaranteed to be `TrivialType` and `StandardLayoutType`.
+ //! Try to make address and length 64 byte, or ideally, `page_size()` aligned where possible.
struct buffer_type
{
//! Type of the pointer to memory.
using pointer = byte *;
+ //! Type of the pointer to memory.
+ using const_pointer = const byte *;
//! Type of the iterator to memory.
using iterator = byte *;
//! Type of the iterator to memory.
@@ -62,29 +65,50 @@ public:
//! Type of the length of memory.
using size_type = size_t;
- //! Pointer to memory to be filled by a read. Try to make this 64 byte, or ideally, `page_size()` aligned where possible.
- pointer data;
- //! The number of bytes to fill into this address. Try to make this a 64 byte multiple, or ideally, a whole multiple of `page_size()`.
- size_type len;
+ //! Default constructor
+ buffer_type() = default;
+ //! Constructor
+ constexpr buffer_type(pointer data, size_type len) noexcept : _data(data), _len(len) {}
+ buffer_type(const buffer_type &) = default;
+ buffer_type(buffer_type &&) = default;
+ buffer_type &operator=(const buffer_type &) = default;
+ buffer_type &operator=(buffer_type &&) = default;
+ ~buffer_type() = default;
+
+ // Emulation of this being a span<byte> in the TS
+
+ //! Returns the address of the bytes for this buffer
+ constexpr pointer data() noexcept { return _data; }
+ //! Returns the address of the bytes for this buffer
+ constexpr const_pointer data() const noexcept { return _data; }
+ //! Returns the number of bytes in this buffer
+ constexpr size_type size() const noexcept { return _len; }
//! Returns an iterator to the beginning of the buffer
- constexpr iterator begin() { return data; }
+ constexpr iterator begin() noexcept { return _data; }
//! Returns an iterator to the beginning of the buffer
- constexpr const_iterator begin() const { return data; }
+ constexpr const_iterator begin() const noexcept { return _data; }
//! Returns an iterator to the beginning of the buffer
- constexpr const_iterator cbegin() const { return data; }
+ constexpr const_iterator cbegin() const noexcept { return _data; }
//! Returns an iterator to after the end of the buffer
- constexpr iterator end() { return data + len; }
+ constexpr iterator end() noexcept { return _data + _len; }
//! Returns an iterator to after the end of the buffer
- constexpr const_iterator end() const { return data + len; }
+ constexpr const_iterator end() const noexcept { return _data + _len; }
//! Returns an iterator to after the end of the buffer
- constexpr const_iterator cend() const { return data + len; }
+ constexpr const_iterator cend() const noexcept { return _data + _len; }
+ private:
+ friend constexpr inline void _check_iovec_match();
+ pointer _data;
+ size_type _len;
};
//! The gather buffer type used by this handle. Guaranteed to be `TrivialType` and `StandardLayoutType`.
+ //! Try to make address and length 64 byte, or ideally, `page_size()` aligned where possible.
struct const_buffer_type
{
//! Type of the pointer to memory.
using pointer = const byte *;
+ //! Type of the pointer to memory.
+ using const_pointer = const byte *;
//! Type of the iterator to memory.
using iterator = const byte *;
//! Type of the iterator to memory.
@@ -92,23 +116,40 @@ public:
//! Type of the length of memory.
using size_type = size_t;
- //! Pointer to memory to be written. Try to make this 64 byte, or ideally, `page_size()` aligned where possible.
- pointer data;
- //! The number of bytes to write from this address. Try to make this a 64 byte multiple, or ideally, a whole multiple of `page_size()`.
- size_type len;
+ //! Default constructor
+ const_buffer_type() = default;
+ //! Constructor
+ constexpr const_buffer_type(pointer data, size_type len) noexcept : _data(data), _len(len) {}
+ const_buffer_type(const const_buffer_type &) = default;
+ const_buffer_type(const_buffer_type &&) = default;
+ const_buffer_type &operator=(const const_buffer_type &) = default;
+ const_buffer_type &operator=(const_buffer_type &&) = default;
+ ~const_buffer_type() = default;
+
+ // Emulation of this being a span<byte> in the TS
+
+ //! Returns the address of the bytes for this buffer
+ constexpr pointer data() noexcept { return _data; }
+ //! Returns the address of the bytes for this buffer
+ constexpr const_pointer data() const noexcept { return _data; }
+ //! Returns the number of bytes in this buffer
+ constexpr size_type size() const noexcept { return _len; }
//! Returns an iterator to the beginning of the buffer
- constexpr iterator begin() { return data; }
+ constexpr iterator begin() noexcept { return _data; }
//! Returns an iterator to the beginning of the buffer
- constexpr const_iterator begin() const { return data; }
+ constexpr const_iterator begin() const noexcept { return _data; }
//! Returns an iterator to the beginning of the buffer
- constexpr const_iterator cbegin() const { return data; }
+ constexpr const_iterator cbegin() const noexcept { return _data; }
//! Returns an iterator to after the end of the buffer
- constexpr iterator end() { return data + len; }
+ constexpr iterator end() noexcept { return _data + _len; }
//! Returns an iterator to after the end of the buffer
- constexpr const_iterator end() const { return data + len; }
+ constexpr const_iterator end() const noexcept { return _data + _len; }
//! Returns an iterator to after the end of the buffer
- constexpr const_iterator cend() const { return data + len; }
+ constexpr const_iterator cend() const noexcept { return _data + _len; }
+ private:
+ pointer _data;
+ size_type _len;
};
#ifndef NDEBUG
static_assert(std::is_trivial<buffer_type>::value, "buffer_type is not a trivial type!");
@@ -155,9 +196,9 @@ public:
static_assert(std::is_standard_layout<io_request<buffers_type>>::value, "io_request<buffers_type> is not a standard layout type!");
#endif
//! The i/o result type used by this handle. Guaranteed to be `TrivialType` apart from construction..
- template <class T> struct io_result : public AFIO_V2_NAMESPACE::result<T>
+ template <class T> struct io_result : public LLFIO_V2_NAMESPACE::result<T>
{
- using Base = AFIO_V2_NAMESPACE::result<T>;
+ using Base = LLFIO_V2_NAMESPACE::result<T>;
size_type _bytes_transferred{static_cast<size_type>(-1)};
#if defined(_MSC_VER) && !defined(__clang__) // workaround MSVC parsing bug
@@ -241,7 +282,7 @@ public:
Microsoft Windows and OS X does not implement scatter-gather file i/o syscalls.
Thus this function will always return `1` in that situation.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC size_t max_buffers() const noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC size_t max_buffers() const noexcept;
/*! \brief Read data from the open handle.
@@ -262,10 +303,10 @@ public:
\mallocs The default synchronous implementation in file_handle performs no memory allocation.
The asynchronous implementation in async_file_handle performs one calloc and one free.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept;
//! \overload
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
io_result<buffers_type> read(extent_type offset, std::initializer_list<buffer_type> lst, deadline d = deadline()) noexcept
{
buffer_type *_reqs = reinterpret_cast<buffer_type *>(alloca(sizeof(buffer_type) * lst.size()));
@@ -295,10 +336,10 @@ public:
\mallocs The default synchronous implementation in file_handle performs no memory allocation.
The asynchronous implementation in async_file_handle performs one calloc and one free.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept;
//! \overload
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
io_result<const_buffers_type> write(extent_type offset, std::initializer_list<const_buffer_type> lst, deadline d = deadline()) noexcept
{
const_buffer_type *_reqs = reinterpret_cast<const_buffer_type *>(alloca(sizeof(const_buffer_type) * lst.size()));
@@ -338,7 +379,7 @@ public:
\errors Any of the values POSIX fdatasync() or Windows NtFlushBuffersFileEx() can return.
\mallocs None.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
virtual io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept = 0;
/*! \class extent_guard
@@ -450,7 +491,7 @@ public:
\mallocs The default synchronous implementation in file_handle performs no memory allocation.
The asynchronous implementation in async_file_handle performs one calloc and one free.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_guard> lock(extent_type offset, extent_type bytes, bool exclusive = true, deadline d = deadline()) noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_guard> lock(extent_type offset, extent_type bytes, bool exclusive = true, deadline d = deadline()) noexcept;
//! \overload
result<extent_guard> try_lock(extent_type offset, extent_type bytes, bool exclusive = true) noexcept { return lock(offset, bytes, exclusive, deadline(std::chrono::seconds(0))); }
//! \overload Locks for shared access
@@ -459,11 +500,11 @@ public:
size_t bytes = 0;
for(auto &i : reqs.buffers)
{
- if(bytes + i.len < bytes)
+ if(bytes + i.size() < bytes)
{
return errc::value_too_large;
}
- bytes += i.len;
+ bytes += i.size();
}
return lock(reqs.offset, bytes, false, d);
}
@@ -473,11 +514,11 @@ public:
size_t bytes = 0;
for(auto &i : reqs.buffers)
{
- if(bytes + i.len < bytes)
+ if(bytes + i.size() < bytes)
{
return errc::value_too_large;
}
- bytes += i.len;
+ bytes += i.size();
}
return lock(reqs.offset, bytes, true, d);
}
@@ -489,7 +530,7 @@ public:
\errors Any of the values POSIX fcntl() can return.
\mallocs None.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(extent_type offset, extent_type bytes) noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void unlock(extent_type offset, extent_type bytes) noexcept;
};
@@ -592,16 +633,16 @@ inline io_handle::io_result<io_handle::const_buffers_type> barrier(io_handle &se
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/io_handle.ipp"
#else
#include "detail/impl/posix/io_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/io_service.hpp b/include/llfio/v2.0/io_service.hpp
index ad898919..e83ea59a 100644
--- a/include/afio/v2.0/io_service.hpp
+++ b/include/llfio/v2.0/io_service.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_IO_SERVICE_H
-#define AFIO_IO_SERVICE_H
+#ifndef LLFIO_IO_SERVICE_H
+#define LLFIO_IO_SERVICE_H
#include "handle.hpp"
@@ -36,14 +36,14 @@ Distributed under the Boost Software License, Version 1.0.
#if defined(__has_include)
#if __has_include(<coroutine>)
#include <coroutine>
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
template<class T = void> using coroutine_handle = std::coroutine_handle<T>;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#elif __has_include(<experimental/coroutine>)
#include <experimental/coroutine>
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
template<class T = void> using coroutine_handle = std::experimental::coroutine_handle<T>;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#else
#error Cannot use C++ Coroutines without the <coroutine> header!
#endif
@@ -58,47 +58,47 @@ AFIO_V2_NAMESPACE_END
// Need to decide which kind of POSIX AIO to use
#ifndef _WIN32
// Right now the only thing we support is POSIX AIO
-#if !defined(AFIO_USE_POSIX_AIO)
+#if !defined(LLFIO_USE_POSIX_AIO)
/*! \brief Undefined to autodetect, 1 to use POSIX AIO, 0 to not use
\warning On FreeBSD the AIO kernel module needs to be loaded for POSIX AIO to work.
Run as root 'kldload aio' or add 'aio_load=YES' in loader.conf.
*/
-#define AFIO_USE_POSIX_AIO 1
+#define LLFIO_USE_POSIX_AIO 1
#endif
// BSD kqueues not implemented yet
-//# if defined(__FreeBSD__) && !defined(AFIO_COMPILE_KQUEUES)
-//# define AFIO_COMPILE_KQUEUES 1
+//# if defined(__FreeBSD__) && !defined(LLFIO_COMPILE_KQUEUES)
+//# define LLFIO_COMPILE_KQUEUES 1
//# endif
-#if AFIO_COMPILE_KQUEUES
-#if defined(AFIO_USE_POSIX_AIO) && !AFIO_USE_POSIX_AIO
+#if LLFIO_COMPILE_KQUEUES
+#if defined(LLFIO_USE_POSIX_AIO) && !LLFIO_USE_POSIX_AIO
#error BSD kqueues must be combined with POSIX AIO!
#endif
-#if !defined(AFIO_USE_POSIX_AIO)
-#define AFIO_USE_POSIX_AIO 1
+#if !defined(LLFIO_USE_POSIX_AIO)
+#define LLFIO_USE_POSIX_AIO 1
#endif
#endif
#if DOXYGEN_SHOULD_SKIP_THIS
//! Undefined to autodetect, 1 to compile in BSD kqueue support, 0 to leave it out
-#define AFIO_COMPILE_KQUEUES 0
+#define LLFIO_COMPILE_KQUEUES 0
#endif
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
// We'll be using POSIX AIO and signal based interruption for post()
#include <csignal>
// Do we have realtime signals?
-#if !defined(AFIO_HAVE_REALTIME_SIGNALS) && defined(_POSIX_RTSIG_MAX) && defined(SIGRTMIN)
-#ifndef AFIO_IO_POST_SIGNAL
-#define AFIO_IO_POST_SIGNAL (-1)
+#if !defined(LLFIO_HAVE_REALTIME_SIGNALS) && defined(_POSIX_RTSIG_MAX) && defined(SIGRTMIN)
+#ifndef LLFIO_IO_POST_SIGNAL
+#define LLFIO_IO_POST_SIGNAL (-1)
#endif
-#define AFIO_HAVE_REALTIME_SIGNALS 1
+#define LLFIO_HAVE_REALTIME_SIGNALS 1
#else
-#ifndef AFIO_IO_POST_SIGNAL
-//! Undefined to autoset to first free SIGRTMIN if realtime signals available, else SIGUSR1. Only used if AFIO_USE_KQUEUES=0.
-#define AFIO_IO_POST_SIGNAL (SIGUSR1)
+#ifndef LLFIO_IO_POST_SIGNAL
+//! Undefined to autoset to first free SIGRTMIN if realtime signals available, else SIGUSR1. Only used if LLFIO_USE_KQUEUES=0.
+#define LLFIO_IO_POST_SIGNAL (SIGUSR1)
#endif
//! Undefined to autodetect. 0 to use non-realtime signals. Note performance in this use case is abysmal.
-#define AFIO_HAVE_REALTIME_SIGNALS 0
+#define LLFIO_HAVE_REALTIME_SIGNALS 0
#endif
struct aiocb;
#endif
@@ -109,7 +109,7 @@ struct aiocb;
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
class io_service;
class async_file_handle;
@@ -122,7 +122,7 @@ initating i/o and completing it onto a single kernel thread.
Unlike the `io_service` in ASIO or the Networking TS, this `io_service`
is much simpler, in particular it is single threaded per instance only
i.e. you must run a separate `io_service` instance one per kernel thread
-if you wish to run i/o processing across multiple threads. AFIO does not
+if you wish to run i/o processing across multiple threads. LLFIO does not
do this for you (and for good reason, unlike socket i/o, it is generally
unwise to distribute file i/o across kernel threads due to the much
more code executable between user space and physical storage i.e. keeping
@@ -143,7 +143,7 @@ if you really must do that.
\snippet coroutines.cpp coroutines_example
*/
-class AFIO_DECL io_service
+class LLFIO_DECL io_service
{
friend class async_file_handle;
@@ -186,9 +186,9 @@ private:
std::deque<post_info> _posts;
using shared_size_type = std::atomic<size_type>;
shared_size_type _work_queued;
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
bool _use_kqueues;
-#if AFIO_COMPILE_KQUEUES
+#if LLFIO_COMPILE_KQUEUES
int _kqueueh;
#endif
std::vector<struct aiocb *> _aiocbsv; // for fast aio_suspend()
@@ -230,43 +230,43 @@ public:
global signal handler via set_interruption_signal() if not yet installed
if on POSIX and BSD kqueues not in use.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC io_service();
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC io_service();
io_service(io_service &&) = delete;
io_service(const io_service &) = delete;
io_service &operator=(io_service &&) = delete;
io_service &operator=(const io_service &) = delete;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~io_service();
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~io_service();
-#ifdef AFIO_IO_POST_SIGNAL
+#ifdef LLFIO_IO_POST_SIGNAL
private:
int _blocked_interrupt_signal{0};
std::atomic<bool> _need_signal{false}; // false = signal not needed, true = signal needed
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC void _block_interruption() noexcept;
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC void _unblock_interruption() noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void _block_interruption() noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void _unblock_interruption() noexcept;
public:
/*! Returns the signal used for interrupting run_until(). Only used on POSIX when
- BSD kqueues are not used. Defaults to AFIO_IO_POST_SIGNAL on platforms which use it.
+ BSD kqueues are not used. Defaults to LLFIO_IO_POST_SIGNAL on platforms which use it.
- \note Only present if AFIO_IO_POST_SIGNAL is defined.
+ \note Only present if LLFIO_IO_POST_SIGNAL is defined.
*/
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC int interruption_signal() noexcept;
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC int interruption_signal() noexcept;
/*! Sets the signal used for interrupting run_until(), returning the former signal
setting. Only used on POSIX when BSD kqueues are not used. Special values are
0 for deinstall global signal handler, and -1 for install to first unused signal
between SIGRTMIN and SIGRTMAX. Changing this while any io_service instances exist
is a bad idea.
- \note Only present if AFIO_IO_POST_SIGNAL is defined.
+ \note Only present if LLFIO_IO_POST_SIGNAL is defined.
*/
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC int set_interruption_signal(int signo = AFIO_IO_POST_SIGNAL);
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC int set_interruption_signal(int signo = LLFIO_IO_POST_SIGNAL);
#endif
-#if AFIO_USE_POSIX_AIO
+#if LLFIO_USE_POSIX_AIO
//! True if this i/o service is using BSD kqueues
bool using_kqueues() const noexcept { return _use_kqueues; }
//! Force disable any use of BSD kqueues
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC void disable_kqueues();
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void disable_kqueues();
#endif
/*! Runs the i/o service for the thread owning this i/o service. Returns true if more
@@ -274,12 +274,12 @@ public:
the deadline passed; `errc::operation_not_supported` if you try to call it from a non-owning thread; `errc::invalid_argument`
if deadline is invalid.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<bool> run_until(deadline d) noexcept;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<bool> run_until(deadline d) noexcept;
//! \overload
result<bool> run() noexcept { return run_until(deadline()); }
private:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC void _post(detail::function_ptr<void(io_service *)> &&f);
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC void _post(detail::function_ptr<void(io_service *)> &&f);
public:
/*! Schedule the callable to be invoked by the thread owning this object and executing `run()` at its next
@@ -312,16 +312,16 @@ public:
#endif
};
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/io_service.ipp"
#else
#include "detail/impl/posix/io_service.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/llfio/v2.0/llfio.hpp b/include/llfio/v2.0/llfio.hpp
new file mode 100644
index 00000000..59984dca
--- /dev/null
+++ b/include/llfio/v2.0/llfio.hpp
@@ -0,0 +1,86 @@
+//! \file v2.0/llfio.hpp The master *versioned* LLFIO include file. All version specific LLFIO consuming libraries should include this header only.
+
+#undef LLFIO_VERSION_MAJOR
+#undef LLFIO_VERSION_MINOR
+#undef LLFIO_VERSION_PATCH
+// Remove any previously defined versioning
+#undef LLFIO_VERSION_REVISION
+#undef LLFIO_VERSION_GLUE2
+#undef LLFIO_VERSION_GLUE
+#undef LLFIO_HEADERS_VERSION
+#undef LLFIO_NAMESPACE_VERSION
+#undef LLFIO_MODULE_NAME
+
+#define LLFIO_VERSION_GLUE2(a, b, c) a##b##c
+#define LLFIO_VERSION_GLUE(a, b, c) LLFIO_VERSION_GLUE2(a, b, c)
+
+// Hard coded as this is a specific version
+#define LLFIO_VERSION_MAJOR 2
+#define LLFIO_VERSION_MINOR 0
+#define LLFIO_VERSION_PATCH 0
+#define LLFIO_VERSION_REVISION 0
+//! \brief The namespace LLFIO_V2_NAMESPACE::v ## LLFIO_NAMESPACE_VERSION
+#define LLFIO_NAMESPACE_VERSION LLFIO_VERSION_GLUE(LLFIO_VERSION_MAJOR, _, LLFIO_VERSION_MINOR)
+
+#if defined(__cpp_modules) || defined(DOXYGEN_SHOULD_SKIP_THIS)
+#if defined(_MSC_VER) && !defined(__clang__)
+//! \brief The LLFIO C++ module name
+#define LLFIO_MODULE_NAME LLFIO_VERSION_GLUE(llfio_v, LLFIO_NAMESPACE_VERSION, )
+#else
+//! \brief The LLFIO C++ module name
+#define LLFIO_MODULE_NAME LLFIO_VERSION_GLUE(llfio_v, LLFIO_NAMESPACE_VERSION, )
+#endif
+#endif
+
+// If C++ Modules are on and we are not compiling the library,
+// we are either generating the interface or importing
+#if defined(__cpp_modules)
+#if defined(GENERATING_LLFIO_MODULE_INTERFACE)
+// We are generating this module's interface
+#define QUICKCPPLIB_HEADERS_ONLY 0
+#define LLFIO_HEADERS_ONLY 0
+#define LLFIO_INCLUDE_ALL
+#elif defined(LLFIO_SOURCE)
+// We are implementing this module
+#define LLFIO_INCLUDE_ALL
+#else
+// We are importing this module
+import LLFIO_MODULE_NAME;
+#undef LLFIO_INCLUDE_ALL
+#endif
+#else
+// C++ Modules not on, therefore include as usual
+#define LLFIO_INCLUDE_ALL
+#endif
+
+#ifdef LLFIO_INCLUDE_ALL
+
+#include "config.hpp"
+
+// Predeclare to keep the single header edition happy
+#include "handle.hpp"
+#include "stat.hpp"
+#include "utils.hpp"
+
+#ifndef LLFIO_LEAN_AND_MEAN
+#include "async_file_handle.hpp"
+#else
+#include "file_handle.hpp"
+#endif
+#include "directory_handle.hpp"
+#include "map_view.hpp"
+#include "statfs.hpp"
+#ifndef LLFIO_LEAN_AND_MEAN
+#include "storage_profile.hpp"
+#endif
+#include "symlink_handle.hpp"
+
+#include "algorithm/cached_parent_handle_adapter.hpp"
+#include "algorithm/shared_fs_mutex/atomic_append.hpp"
+#include "algorithm/shared_fs_mutex/byte_ranges.hpp"
+#include "algorithm/shared_fs_mutex/lock_files.hpp"
+#include "algorithm/shared_fs_mutex/memory_map.hpp"
+#include "algorithm/shared_fs_mutex/safe_byte_ranges.hpp"
+#include "algorithm/trivial_vector.hpp"
+
+#endif
diff --git a/include/afio/v2.0/logging.hpp b/include/llfio/v2.0/logging.hpp
index 76030684..0cce2ccc 100644
--- a/include/afio/v2.0/logging.hpp
+++ b/include/llfio/v2.0/logging.hpp
@@ -1,4 +1,4 @@
-/* Configures AFIO
+/* LLFIO logging
(C) 2015-2018 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: Dec 2015
@@ -22,25 +22,25 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_LOGGING_HPP
-#define AFIO_LOGGING_HPP
+#ifndef LLFIO_LOGGING_HPP
+#define LLFIO_LOGGING_HPP
#include "config.hpp"
-#if AFIO_LOGGING_LEVEL
+#if LLFIO_LOGGING_LEVEL
/*! \todo TODO FIXME Replace in-memory log with memory map file backed log.
*/
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-//! The log used by AFIO
-inline AFIO_DECL QUICKCPPLIB_NAMESPACE::ringbuffer_log::simple_ringbuffer_log<AFIO_LOGGING_MEMORY> &log() noexcept
+//! The log used by LLFIO
+inline LLFIO_DECL QUICKCPPLIB_NAMESPACE::ringbuffer_log::simple_ringbuffer_log<LLFIO_LOGGING_MEMORY> &log() noexcept
{
- static QUICKCPPLIB_NAMESPACE::ringbuffer_log::simple_ringbuffer_log<AFIO_LOGGING_MEMORY> _log(static_cast<QUICKCPPLIB_NAMESPACE::ringbuffer_log::level>(AFIO_LOGGING_LEVEL));
-#ifdef AFIO_LOG_TO_OSTREAM
- if(_log.immediate() != &AFIO_LOG_TO_OSTREAM)
+ static QUICKCPPLIB_NAMESPACE::ringbuffer_log::simple_ringbuffer_log<LLFIO_LOGGING_MEMORY> _log(static_cast<QUICKCPPLIB_NAMESPACE::ringbuffer_log::level>(LLFIO_LOGGING_LEVEL));
+#ifdef LLFIO_LOG_TO_OSTREAM
+ if(_log.immediate() != &LLFIO_LOG_TO_OSTREAM)
{
- _log.immediate(&AFIO_LOG_TO_OSTREAM);
+ _log.immediate(&LLFIO_LOG_TO_OSTREAM);
}
#endif
return _log;
@@ -67,14 +67,14 @@ public:
};
// Infrastructure for recording the current path for when failure occurs
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
namespace detail
{
// Our thread local store
struct tls_errored_results_t
{
uint32_t this_thread_id{QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id()};
- handle *current_handle{nullptr}; // The current handle for this thread. Changed via RAII via AFIO_LOG_FUNCTION_CALL, see below.
+ handle *current_handle{nullptr}; // The current handle for this thread. Changed via RAII via LLFIO_LOG_FUNCTION_CALL, see below.
bool reentering_self{false}; // Prevents any failed call to current_path() by us reentering ourselves
char paths[190][16]{}; // Last 190 chars of path
@@ -96,11 +96,11 @@ namespace detail
};
inline tls_errored_results_t &tls_errored_results()
{
-#if AFIO_THREAD_LOCAL_IS_CXX11
+#if LLFIO_THREAD_LOCAL_IS_CXX11
static thread_local tls_errored_results_t v;
return v;
#else
- static AFIO_THREAD_LOCAL tls_errored_results_t *v;
+ static LLFIO_THREAD_LOCAL tls_errored_results_t *v;
if(!v)
{
v = new tls_errored_results_t;
@@ -146,68 +146,68 @@ namespace detail
~tls_current_handle_holder() = default;
template <class T> explicit tls_current_handle_holder(T && /*unused*/) {}
};
-#define AFIO_LOG_INST_TO_TLS(inst) ::AFIO_V2_NAMESPACE::detail::tls_current_handle_holder<std::is_base_of<::AFIO_V2_NAMESPACE::handle, std::decay_t<std::remove_pointer_t<decltype(inst)>>>::value> AFIO_UNIQUE_NAME(inst)
+#define LLFIO_LOG_INST_TO_TLS(inst) ::LLFIO_V2_NAMESPACE::detail::tls_current_handle_holder<std::is_base_of<::LLFIO_V2_NAMESPACE::handle, std::decay_t<std::remove_pointer_t<decltype(inst)>>>::value> LLFIO_UNIQUE_NAME(inst)
} // namespace detail
-#else // AFIO_DISABLE_PATHS_IN_FAILURE_INFO
-#define AFIO_LOG_INST_TO_TLS(inst)
-#endif // AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#else // LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#define LLFIO_LOG_INST_TO_TLS(inst)
+#endif // LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#ifndef AFIO_LOG_FATAL_TO_CERR
+#ifndef LLFIO_LOG_FATAL_TO_CERR
#include <cstdio>
-#define AFIO_LOG_FATAL_TO_CERR(expr) \
+#define LLFIO_LOG_FATAL_TO_CERR(expr) \
fprintf(stderr, "%s\n", (expr)); \
fflush(stderr)
#endif
-#endif // AFIO_LOGGING_LEVEL
+#endif // LLFIO_LOGGING_LEVEL
-#if AFIO_LOGGING_LEVEL >= 1
-#define AFIO_LOG_FATAL(inst, message) \
+#if LLFIO_LOGGING_LEVEL >= 1
+#define LLFIO_LOG_FATAL(inst, message) \
{ \
- ::AFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::fatal, (message), ::AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (AFIO_LOG_BACKTRACE_LEVELS & (1U << 1U)) ? nullptr : __func__, __LINE__); \
- AFIO_LOG_FATAL_TO_CERR(message); \
+ ::LLFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::fatal, (message), ::LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (LLFIO_LOG_BACKTRACE_LEVELS & (1U << 1U)) ? nullptr : __func__, __LINE__); \
+ LLFIO_LOG_FATAL_TO_CERR(message); \
}
#else
-#define AFIO_LOG_FATAL(inst, message) AFIO_LOG_FATAL_TO_CERR(message)
+#define LLFIO_LOG_FATAL(inst, message) LLFIO_LOG_FATAL_TO_CERR(message)
#endif
-#if AFIO_LOGGING_LEVEL >= 2
-#define AFIO_LOG_ERROR(inst, message) \
- ::AFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::error, (message), ::AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (AFIO_LOG_BACKTRACE_LEVELS & (1U << 2U)) ? nullptr : __func__, __LINE__)
+#if LLFIO_LOGGING_LEVEL >= 2
+#define LLFIO_LOG_ERROR(inst, message) \
+ ::LLFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::error, (message), ::LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (LLFIO_LOG_BACKTRACE_LEVELS & (1U << 2U)) ? nullptr : __func__, __LINE__)
#else
-#define AFIO_LOG_ERROR(inst, message)
+#define LLFIO_LOG_ERROR(inst, message)
#endif
-#if AFIO_LOGGING_LEVEL >= 3
-#define AFIO_LOG_WARN(inst, message) \
- ::AFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::warn, (message), ::AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (AFIO_LOG_BACKTRACE_LEVELS & (1U << 3U)) ? nullptr : __func__, __LINE__)
+#if LLFIO_LOGGING_LEVEL >= 3
+#define LLFIO_LOG_WARN(inst, message) \
+ ::LLFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::warn, (message), ::LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (LLFIO_LOG_BACKTRACE_LEVELS & (1U << 3U)) ? nullptr : __func__, __LINE__)
#else
-#define AFIO_LOG_WARN(inst, message)
+#define LLFIO_LOG_WARN(inst, message)
#endif
-#if AFIO_LOGGING_LEVEL >= 4
-#define AFIO_LOG_INFO(inst, message) \
- ::AFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::info, (message), ::AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (AFIO_LOG_BACKTRACE_LEVELS & (1U << 4U)) ? nullptr : __func__, __LINE__)
+#if LLFIO_LOGGING_LEVEL >= 4
+#define LLFIO_LOG_INFO(inst, message) \
+ ::LLFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::info, (message), ::LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (LLFIO_LOG_BACKTRACE_LEVELS & (1U << 4U)) ? nullptr : __func__, __LINE__)
// Need to expand out our namespace into a string
-#define AFIO_LOG_STRINGIFY9(s) #s "::"
-#define AFIO_LOG_STRINGIFY8(s) AFIO_LOG_STRINGIFY9(s)
-#define AFIO_LOG_STRINGIFY7(s) AFIO_LOG_STRINGIFY8(s)
-#define AFIO_LOG_STRINGIFY6(s) AFIO_LOG_STRINGIFY7(s)
-#define AFIO_LOG_STRINGIFY5(s) AFIO_LOG_STRINGIFY6(s)
-#define AFIO_LOG_STRINGIFY4(s) AFIO_LOG_STRINGIFY5(s)
-#define AFIO_LOG_STRINGIFY3(s) AFIO_LOG_STRINGIFY4(s)
-#define AFIO_LOG_STRINGIFY2(s) AFIO_LOG_STRINGIFY3(s)
-#define AFIO_LOG_STRINGIFY(s) AFIO_LOG_STRINGIFY2(s)
-AFIO_V2_NAMESPACE_BEGIN
+#define LLFIO_LOG_STRINGIFY9(s) #s "::"
+#define LLFIO_LOG_STRINGIFY8(s) LLFIO_LOG_STRINGIFY9(s)
+#define LLFIO_LOG_STRINGIFY7(s) LLFIO_LOG_STRINGIFY8(s)
+#define LLFIO_LOG_STRINGIFY6(s) LLFIO_LOG_STRINGIFY7(s)
+#define LLFIO_LOG_STRINGIFY5(s) LLFIO_LOG_STRINGIFY6(s)
+#define LLFIO_LOG_STRINGIFY4(s) LLFIO_LOG_STRINGIFY5(s)
+#define LLFIO_LOG_STRINGIFY3(s) LLFIO_LOG_STRINGIFY4(s)
+#define LLFIO_LOG_STRINGIFY2(s) LLFIO_LOG_STRINGIFY3(s)
+#define LLFIO_LOG_STRINGIFY(s) LLFIO_LOG_STRINGIFY2(s)
+LLFIO_V2_NAMESPACE_BEGIN
namespace detail
{
- // Returns the AFIO namespace as a string
- inline span<char> afio_namespace_string()
+ // Returns the LLFIO namespace as a string
+ inline span<char> llfio_namespace_string()
{
static char buffer[64];
static size_t length;
if(length)
return span<char>(buffer, length);
- const char *src = AFIO_LOG_STRINGIFY(AFIO_V2_NAMESPACE);
+ const char *src = LLFIO_LOG_STRINGIFY(LLFIO_V2_NAMESPACE);
char *bufferp = buffer;
for(; *src && (bufferp - buffer) < (ptrdiff_t) sizeof(buffer); src++)
{
@@ -225,7 +225,7 @@ namespace detail
static size_t length;
if(length)
return span<char>(buffer, length);
- const char *src = AFIO_LOG_STRINGIFY(OUTCOME_V2_NAMESPACE);
+ const char *src = LLFIO_LOG_STRINGIFY(OUTCOME_V2_NAMESPACE);
char *bufferp = buffer;
for(; *src && (bufferp - buffer) < (ptrdiff_t) sizeof(buffer); src++)
{
@@ -236,10 +236,10 @@ namespace detail
length = bufferp - buffer;
return span<char>(buffer, length);
}
- // Strips a __PRETTY_FUNCTION__ of all instances of ::AFIO_V2_NAMESPACE:: and ::AFIO_V2_NAMESPACE::
+ // Strips a __PRETTY_FUNCTION__ of all instances of ::LLFIO_V2_NAMESPACE:: and ::LLFIO_V2_NAMESPACE::
inline void strip_pretty_function(char *out, size_t bytes, const char *in)
{
- const span<char> remove1 = afio_namespace_string();
+ const span<char> remove1 = llfio_namespace_string();
const span<char> remove2 = outcome_namespace_string();
for(--bytes; bytes && *in; --bytes)
{
@@ -251,49 +251,49 @@ namespace detail
}
*out = 0;
}
- template <class T> void log_inst_to_info(T &&inst, const char *buffer) { AFIO_LOG_INFO(inst, buffer); }
+ template <class T> void log_inst_to_info(T &&inst, const char *buffer) { LLFIO_LOG_INFO(inst, buffer); }
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#ifdef _MSC_VER
-#define AFIO_LOG_FUNCTION_CALL(inst) \
+#define LLFIO_LOG_FUNCTION_CALL(inst) \
if(log().log_level() >= log_level::info) \
{ \
char buffer[256]; \
- ::AFIO_V2_NAMESPACE::detail::strip_pretty_function(buffer, sizeof(buffer), __FUNCSIG__); \
- ::AFIO_V2_NAMESPACE::detail::log_inst_to_info(inst, buffer); \
+ ::LLFIO_V2_NAMESPACE::detail::strip_pretty_function(buffer, sizeof(buffer), __FUNCSIG__); \
+ ::LLFIO_V2_NAMESPACE::detail::log_inst_to_info(inst, buffer); \
} \
- AFIO_LOG_INST_TO_TLS(inst)
+ LLFIO_LOG_INST_TO_TLS(inst)
#else
-#define AFIO_LOG_FUNCTION_CALL(inst) \
+#define LLFIO_LOG_FUNCTION_CALL(inst) \
if(log().log_level() >= log_level::info) \
{ \
char buffer[256]; \
- ::AFIO_V2_NAMESPACE::detail::strip_pretty_function(buffer, sizeof(buffer), __PRETTY_FUNCTION__); \
- ::AFIO_V2_NAMESPACE::detail::log_inst_to_info(inst, buffer); \
+ ::LLFIO_V2_NAMESPACE::detail::strip_pretty_function(buffer, sizeof(buffer), __PRETTY_FUNCTION__); \
+ ::LLFIO_V2_NAMESPACE::detail::log_inst_to_info(inst, buffer); \
} \
- AFIO_LOG_INST_TO_TLS(inst)
+ LLFIO_LOG_INST_TO_TLS(inst)
#endif
#else
-#define AFIO_LOG_INFO(inst, message)
-#define AFIO_LOG_FUNCTION_CALL(inst) AFIO_LOG_INST_TO_TLS(inst)
+#define LLFIO_LOG_INFO(inst, message)
+#define LLFIO_LOG_FUNCTION_CALL(inst) LLFIO_LOG_INST_TO_TLS(inst)
#endif
-#if AFIO_LOGGING_LEVEL >= 5
-#define AFIO_LOG_DEBUG(inst, message) \
- ::AFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::debug, ::AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (AFIO_LOG_BACKTRACE_LEVELS & (1U << 5U)) ? nullptr : __func__, __LINE__)
+#if LLFIO_LOGGING_LEVEL >= 5
+#define LLFIO_LOG_DEBUG(inst, message) \
+ ::LLFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::debug, ::LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (LLFIO_LOG_BACKTRACE_LEVELS & (1U << 5U)) ? nullptr : __func__, __LINE__)
#else
-#define AFIO_LOG_DEBUG(inst, message)
+#define LLFIO_LOG_DEBUG(inst, message)
#endif
-#if AFIO_LOGGING_LEVEL >= 6
-#define AFIO_LOG_ALL(inst, message) \
- ::AFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::all, (message), ::AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (AFIO_LOG_BACKTRACE_LEVELS & (1U << 6U)) ? nullptr : __func__, __LINE__)
+#if LLFIO_LOGGING_LEVEL >= 6
+#define LLFIO_LOG_ALL(inst, message) \
+ ::LLFIO_V2_NAMESPACE::log().emplace_back(QUICKCPPLIB_NAMESPACE::ringbuffer_log::level::all, (message), ::LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<unsigned>(inst), QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id(), (LLFIO_LOG_BACKTRACE_LEVELS & (1U << 6U)) ? nullptr : __func__, __LINE__)
#else
-#define AFIO_LOG_ALL(inst, message)
+#define LLFIO_LOG_ALL(inst, message)
#endif
-#if !AFIO_EXPERIMENTAL_STATUS_CODE
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
-AFIO_V2_NAMESPACE_BEGIN
+#if !LLFIO_EXPERIMENTAL_STATUS_CODE
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
+LLFIO_V2_NAMESPACE_BEGIN
namespace detail
{
@@ -315,7 +315,7 @@ namespace detail
ret.append("]");
}
}
-#if AFIO_LOGGING_LEVEL >= 2
+#if LLFIO_LOGGING_LEVEL >= 2
if(src._log_id != static_cast<uint32_t>(-1))
{
if(log().valid(src._log_id))
@@ -329,7 +329,7 @@ namespace detail
}
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
#endif
diff --git a/include/afio/v2.0/map_handle.hpp b/include/llfio/v2.0/map_handle.hpp
index 8c66450a..d84df116 100644
--- a/include/afio/v2.0/map_handle.hpp
+++ b/include/llfio/v2.0/map_handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_MAP_HANDLE_H
-#define AFIO_MAP_HANDLE_H
+#ifndef LLFIO_MAP_HANDLE_H
+#define LLFIO_MAP_HANDLE_H
#include "file_handle.hpp"
@@ -34,7 +34,7 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
/*! \class section_handle
\brief A handle to a source of mapped memory.
@@ -48,7 +48,7 @@ On Windows the native handle of this handle is that of the NT kernel section obj
a cloned file descriptor of the backing storage if there is backing storage, else it will be the
aforementioned file descriptor to an unnamed inode.
*/
-class AFIO_DECL section_handle : public handle
+class LLFIO_DECL section_handle : public handle
{
public:
using extent_type = handle::extent_type;
@@ -80,8 +80,8 @@ protected:
flag _flag{flag::none};
public:
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~section_handle() override;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~section_handle() override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
//! Default constructor
constexpr section_handle() {} // NOLINT
//! Construct a section handle using the given native handle type for the section and the given i/o handle for the backing storage
@@ -110,7 +110,7 @@ public:
//! No copy assignment
section_handle &operator=(const section_handle &) = delete;
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(section_handle &o) noexcept
{
section_handle temp(std::move(*this));
@@ -125,8 +125,8 @@ public:
\errors Any of the values POSIX dup(), open() or NtCreateSection() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<section_handle> section(file_handle &backing, extent_type maximum_size, flag _flag) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<section_handle> section(file_handle &backing, extent_type maximum_size, flag _flag) noexcept;
/*! \brief Create a memory section backed by a file.
\param backing The handle to use as backing storage.
\param bytes The initial size of this section, which cannot be larger than any backing file. Zero means to use `backing.maximum_extent()`.
@@ -135,7 +135,7 @@ public:
\errors Any of the values POSIX dup(), open() or NtCreateSection() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static result<section_handle> section(file_handle &backing, extent_type bytes = 0) noexcept { return section(backing, bytes, backing.is_writable() ? (flag::readwrite) : (flag::read)); }
/*! \brief Create a memory section backed by an anonymous, managed file.
\param bytes The initial size of this section. Cannot be zero.
@@ -144,8 +144,8 @@ public:
\errors Any of the values POSIX dup(), open() or NtCreateSection() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<section_handle> section(extent_type bytes, const path_handle &dirh = path_discovery::storage_backed_temporary_files_directory(), flag _flag = flag::read | flag::write) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<section_handle> section(extent_type bytes, const path_handle &dirh = path_discovery::storage_backed_temporary_files_directory(), flag _flag = flag::read | flag::write) noexcept;
//! Returns the memory section's flags
flag section_flags() const noexcept { return _flag; }
@@ -158,8 +158,8 @@ public:
//! Returns the borrowed native handle backing this section
native_handle_type backing_native_handle() const noexcept { return _backing != nullptr ? _backing->native_handle() : native_handle_type(); }
//! Return the current length of the memory section.
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<extent_type> length() const noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<extent_type> length() const noexcept;
/*! Resize the current maximum permitted extent of the memory section to the given extent.
\param newsize The new size of the memory section, which cannot be zero. Specify zero to use `backing.maximum_extent()`.
@@ -167,8 +167,8 @@ public:
\errors Any of the values `NtExtendSection()` or `ftruncate()` can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<extent_type> truncate(extent_type newsize = 0) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<extent_type> truncate(extent_type newsize = 0) noexcept;
};
inline std::ostream &operator<<(std::ostream &s, const section_handle::flag &v)
{
@@ -225,7 +225,7 @@ inline std::ostream &operator<<(std::ostream &s, const section_handle::flag &v)
{
temp = "none";
}
- return s << "afio::section_handle::flag::" << temp;
+ return s << "llfio::section_handle::flag::" << temp;
}
//! \brief Constructor for `section_handle`
@@ -271,13 +271,13 @@ This is vast overkill if you are using non-volatile RAM, so a special *inlined*
taking a single buffer and no other arguments is also provided. This calls the appropriate architecture-specific
instructions to cause the CPU to write all preceding writes out of the write buffers and CPU caches to main
memory, so for Intel CPUs this would be `CLWB <each cache line>; SFENCE;`. As this is inlined, it ought to
-produce optimal code. If your CPU does not support the requisite instructions (or AFIO has not added support),
+produce optimal code. If your CPU does not support the requisite instructions (or LLFIO has not added support),
and empty buffer will be returned to indicate that nothing was barriered, same as the normal `barrier()`
function.
\sa `mapped_file_handle`, `algorithm::mapped_span`
*/
-class AFIO_DECL map_handle : public io_handle
+class LLFIO_DECL map_handle : public io_handle
{
friend class mapped_file_handle;
@@ -311,7 +311,7 @@ protected:
public:
//! Default constructor
constexpr map_handle() {} // NOLINT
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~map_handle() override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~map_handle() override;
//! Implicit move construction of map_handle permitted
constexpr map_handle(map_handle &&o) noexcept : io_handle(std::move(o)), _section(o._section), _addr(o._addr), _offset(o._offset), _reservation(o._reservation), _length(o._length), _flag(o._flag)
{
@@ -334,7 +334,7 @@ public:
//! No copy assignment
map_handle &operator=(const map_handle &) = delete;
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(map_handle &o) noexcept
{
map_handle temp(std::move(*this));
@@ -343,12 +343,12 @@ public:
}
//! Unmap the mapped view.
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
//! Releases the mapped view, but does NOT release the native handle.
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override;
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
/*! Lightweight inlined barrier which causes the CPU to write out all buffered writes and dirty cache lines
in the request to main memory.
\return The cache lines actually barriered. This may be empty. This function does not return an error.
@@ -356,29 +356,30 @@ public:
\param evict Whether to also evict the cache lines from CPU caches, useful if they will not be used again.
Upon return, one knows that memory in the returned buffer has been barriered
- (it may be empty if there is no support for this operation in AFIO, or if the current CPU does not
+ (it may be empty if there is no support for this operation in LLFIO, or if the current CPU does not
support this operation). You may find the `is_nvram()` observer of particular use here.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static const_buffer_type barrier(const_buffer_type req, bool evict = false) noexcept
{
- const_buffer_type ret{(const_buffer_type::pointer)(((uintptr_t) req.data) & 31), 0};
- ret.len = req.data + req.len - ret.data;
- for(const_buffer_type::pointer addr = ret.data; addr < ret.data + ret.len; addr += 32)
+ auto *tp = (const_buffer_type::pointer)(((uintptr_t) req.data()) & 31);
+ const_buffer_type ret{tp, (size_t)(req.data() + req.size() - tp)};
+ for(const_buffer_type::pointer addr = ret.data(); addr < ret.data() + ret.size(); addr += 32)
{
// Slightly UB ...
auto *p = reinterpret_cast<const persistent<byte> *>(addr);
if(memory_flush_none == p->flush(evict ? memory_flush_evict : memory_flush_retain))
{
- req.len = 0;
+ ret = {tp, 0};
break;
}
}
return ret;
}
- /*! Create new memory and map it into view.
- \param bytes How many bytes to create and map. Typically will be rounded up to a multiple of the page size (see `utils::page_sizes()`) on POSIX, 64Kb on Windows.
+ /*! Map unused memory into view, creating new memory if insufficient unused memory is available. Note that the memory mapped by this call may contain non-zero bits (recycled memory) unless `zeroed` is true.
+ \param bytes How many bytes to map. Typically will be rounded up to a multiple of the page size (see `utils::page_sizes()`) on POSIX, 64Kb on Windows.
+ \param zeroed Set to true if only all bits zeroed memory is wanted.
\param _flag The permissions with which to map the view. `flag::none` can be useful for reserving virtual address space without committing system resources, use commit() to later change availability of memory.
\note On Microsoft Windows this constructor uses the faster VirtualAlloc() which creates less versatile page backed memory. If you want anonymous memory
@@ -388,8 +389,8 @@ public:
\errors Any of the values POSIX mmap() or VirtualAlloc() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<map_handle> map(size_type bytes, section_handle::flag _flag = section_handle::flag::readwrite) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<map_handle> map(size_type bytes, bool zeroed = false, section_handle::flag _flag = section_handle::flag::readwrite) noexcept;
/*! Create a memory mapped view of a backing storage, optionally reserving additional address space for later growth.
\param section A memory section handle specifying the backing storage to use.
@@ -399,8 +400,8 @@ public:
\errors Any of the values POSIX mmap() or NtMapViewOfSection() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<map_handle> map(section_handle &section, size_type bytes = 0, extent_type offset = 0, section_handle::flag _flag = section_handle::flag::readwrite) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<map_handle> map(section_handle &section, size_type bytes = 0, extent_type offset = 0, section_handle::flag _flag = section_handle::flag::readwrite) noexcept;
//! The memory section this handle is using
section_handle *section() const noexcept { return _section; }
@@ -417,7 +418,7 @@ public:
size_type capacity() const noexcept { return _reservation; }
//! The size of the memory map. This is the accessible size, NOT the reservation size.
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
size_type length() const noexcept { return _length; }
//! True if the map is of non-volatile RAM
@@ -465,14 +466,14 @@ public:
a memory map).
\errors Any of the values POSIX `mremap()`, `mmap(addr)` or `VirtualAlloc(addr)` can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_type> truncate(size_type newsize, bool permit_relocation = false) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_type> truncate(size_type newsize, bool permit_relocation = false) noexcept;
//! Ask the system to commit the system resources to make the memory represented by the buffer available with the given permissions. addr and length should be page aligned (see utils::page_sizes()), if not the returned buffer is the region actually committed.
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<buffer_type> commit(buffer_type region, section_handle::flag flag = section_handle::flag::readwrite) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<buffer_type> commit(buffer_type region, section_handle::flag flag = section_handle::flag::readwrite) noexcept;
//! Ask the system to make the memory represented by the buffer unavailable and to decommit the system resources representing them. addr and length should be page aligned (see utils::page_sizes()), if not the returned buffer is the region actually decommitted.
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<buffer_type> decommit(buffer_type region) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<buffer_type> decommit(buffer_type region) noexcept;
/*! Zero the memory represented by the buffer. Differs from zero() because it acts on mapped memory, but may call zero() internally.
@@ -481,7 +482,7 @@ public:
freshly zeroed ones making this a very efficient way of zeroing large ranges of memory.
\errors Any of the errors returnable by madvise() or DiscardVirtualMemory or the zero() function.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<void> zero_memory(buffer_type region) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<void> zero_memory(buffer_type region) noexcept;
/*! Ask the system to unset the dirty flag for the memory represented by the buffer. This will prevent any changes not yet sent to the backing storage from being sent in the future, also if the system kicks out this page and reloads it you may see some edition of the underlying storage instead of what was here. addr
and length should be page aligned (see utils::page_sizes()), if not the returned buffer is the region actually undirtied.
@@ -491,10 +492,10 @@ public:
\note Microsoft Windows does not support unsetting the dirty flag on file backed maps, so on Windows this call does nothing.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<buffer_type> do_not_store(buffer_type region) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<buffer_type> do_not_store(buffer_type region) noexcept;
//! Ask the system to begin to asynchronously prefetch the span of memory regions given, returning the regions actually prefetched. Note that on Windows 7 or earlier the system call to implement this was not available, and so you will see an empty span returned.
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<span<buffer_type>> prefetch(span<buffer_type> regions) noexcept;
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<span<buffer_type>> prefetch(span<buffer_type> regions) noexcept;
//! \overload
static result<buffer_type> prefetch(buffer_type region) noexcept
{
@@ -515,8 +516,8 @@ public:
\errors None, though the various signals and structured exception throws common to using memory maps may occur.
\mallocs None.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override;
using io_handle::read;
/*! \brief Write data to the mapped view.
@@ -535,8 +536,8 @@ public:
of the raised signal, but it is by far the most likely.
\mallocs None if a `QUICKCPPLIB_NAMESPACE::signal_guard_install` is already instanced.
*/
- AFIO_MAKE_FREE_FUNCTION
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override;
using io_handle::write;
};
@@ -628,7 +629,7 @@ in the request to main memory.
\param evict Whether to also evict the cache lines from CPU caches, useful if they will not be used again.
Upon return, one knows that memory in the returned buffer has been barriered
-(it may be empty if there is no support for this operation in AFIO, or if the current CPU does not
+(it may be empty if there is no support for this operation in LLFIO, or if the current CPU does not
support this operation). You may find the `is_nvram()` observer of particular use here.
*/
inline map_handle::const_buffer_type barrier(map_handle &self, map_handle::const_buffer_type req, bool evict = false) noexcept
@@ -646,9 +647,9 @@ VirtualAlloc() memory cannot do.
\errors Any of the values POSIX mmap() or VirtualAlloc() can return.
*/
-inline result<map_handle> map(map_handle::size_type bytes, section_handle::flag _flag = section_handle::flag::readwrite) noexcept
+inline result<map_handle> map(map_handle::size_type bytes, bool zeroed = false, section_handle::flag _flag = section_handle::flag::readwrite) noexcept
{
- return map_handle::map(std::forward<decltype(bytes)>(bytes), std::forward<decltype(_flag)>(_flag));
+ return map_handle::map(std::forward<decltype(bytes)>(bytes), zeroed, std::forward<decltype(_flag)>(_flag));
}
/*! Create a memory mapped view of a backing storage, optionally reserving additional address space for later growth.
\param section A memory section handle specifying the backing storage to use.
@@ -729,16 +730,16 @@ inline map_handle::io_result<map_handle::const_buffers_type> write(map_handle &s
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/map_handle.ipp"
#else
#include "detail/impl/posix/map_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/llfio/v2.0/map_view.hpp b/include/llfio/v2.0/map_view.hpp
new file mode 100644
index 00000000..75bab5b0
--- /dev/null
+++ b/include/llfio/v2.0/map_view.hpp
@@ -0,0 +1,87 @@
+/* A typed view of a mapped section
+(C) 2017-2018 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
+File Created: Aug 2017
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef LLFIO_MAP_VIEW_HPP
+#define LLFIO_MAP_VIEW_HPP
+
+#include "mapped.hpp"
+
+//! \file map_view.hpp Provides typed view of mapped section.
+
+LLFIO_V2_NAMESPACE_BEGIN
+
+/*! \brief Provides a lightweight typed view of a `map_handle`, a `mapped_file_handle`
+or a `mapped<T>` suitable for feeding to STL algorithms or the Ranges TS.
+
+This is the correct type to use when passing non-owning views of mapped data
+around between functions. Where you wish the view to be (possibly) owning,
+you may find the non-lightweight `mapped<T>` of more use.
+*/
+template <class T> class map_view : public span<T>
+{
+public:
+ //! The extent type.
+ using extent_type = typename section_handle::extent_type;
+ //! The size type.
+ using size_type = typename section_handle::size_type;
+
+public:
+ //! Default constructor
+ constexpr map_view() {} // NOLINT
+
+ /*! Implicitly construct a mapped view of the given mapped data.
+
+ \param map The mapped data to take a view upon.
+ \param length The number of items to map, use -1 to mean the length of the input view.
+ \param offset The item offset into the mapped file handle.
+ */
+ map_view(mapped<T> &map, size_type length = (size_type) -1, size_type offset = 0) // NOLINT
+ : span<T>(map.begin() + offset, (length == (size_type) -1) ? (map.size() - offset) : length) // NOLINT
+ {
+ }
+ /*! Construct a mapped view of the given map handle.
+
+ \param mh The map handle to use.
+ \param length The number of items to map, use -1 to mean the length of the map handle divided by `sizeof(T)`.
+ \param byteoffset The byte offset into the map handle, this does not need to be a multiple of the page size.
+ */
+ explicit map_view(map_handle &mh, size_type length = (size_type) -1, extent_type byteoffset = 0) // NOLINT
+ : span<T>(reinterpret_cast<T *>(mh.address() + byteoffset), (length == (size_type) -1) ? ((mh.length() - byteoffset) / sizeof(T)) : length) // NOLINT
+ {
+ }
+ /*! Construct a mapped view of the given mapped file handle.
+
+ \param mfh The mapped file handle to take a view upon.
+ \param length The number of items to map, use -1 to mean the length of the section handle divided by `sizeof(T)`.
+ \param byteoffset The byte offset into the mapped file handle, this does not need to be a multiple of the page size.
+ */
+ explicit map_view(mapped_file_handle &mfh, size_type length = (size_type) -1, extent_type byteoffset = 0) // NOLINT
+ : span<T>(reinterpret_cast<T *>(mfh.address() + byteoffset), (length == (size_type) -1) ? ((mfh.maximum_extent().value() - byteoffset) / sizeof(T)) : length) // NOLINT
+ {
+ }
+};
+
+LLFIO_V2_NAMESPACE_END
+
+#endif
diff --git a/include/llfio/v2.0/mapped.hpp b/include/llfio/v2.0/mapped.hpp
new file mode 100644
index 00000000..e723ca75
--- /dev/null
+++ b/include/llfio/v2.0/mapped.hpp
@@ -0,0 +1,136 @@
+/* A typed view of a mapped section
+(C) 2017-2018 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
+File Created: Aug 2017
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef LLFIO_MAPPED_HPP
+#define LLFIO_MAPPED_HPP
+
+#include "mapped_file_handle.hpp"
+#include "utils.hpp"
+
+//! \file mapped.hpp Provides typed view of mapped section.
+
+LLFIO_V2_NAMESPACE_BEGIN
+
+/*! \brief Provides an owning, typed view of memory mapped from a `section_handle` or a `file_handle` suitable
+for feeding to STL algorithms or the Ranges TS.
+
+This opens a new `map_handle` (and if necessary a `section_handle`) onto the requested offset and length
+of the supplied source, and thus is an *owning* view of mapped memory. It can be moved, but not copied.
+If you wish to pass around a non-owning view, see `map_view<T>`.
+
+Optionally can issue a blocking write barrier on destruction of the mapped view by setting the flag
+`section_handle::flag::barrier_on_close`, thus forcing any changes to data referred to by this
+to storage before the destructor returns.
+*/
+template <class T> class mapped : public span<T>
+{
+public:
+ //! The extent type.
+ using extent_type = typename section_handle::extent_type;
+ //! The size type.
+ using size_type = typename section_handle::size_type;
+
+private:
+ section_handle _sectionh;
+ map_handle _maph;
+ mapped(file_handle *backing, size_type maximum_size, extent_type page_offset, extent_type offset, section_handle *sh, size_type bytes, section_handle::flag _flag) // NOLINT
+ : _sectionh((backing != nullptr) ? section_handle::section(*backing, maximum_size, _flag).value() : section_handle()), //
+ _maph(map_handle::map((sh != nullptr) ? *sh : _sectionh, (bytes == 0) ? 0 : bytes + (offset - page_offset), page_offset, _flag).value())
+ {
+ if(sh == nullptr)
+ {
+ sh = &_sectionh;
+ }
+ offset -= page_offset;
+ byte *addr = _maph.address() + offset;
+ size_t len = sh->length().value() - offset; // use section length, not mapped length as mapped length is rounded up to page size
+ if(bytes != 0 && bytes < len)
+ {
+ len = bytes;
+ }
+ static_cast<span<T> &>(*this) = span<T>(reinterpret_cast<T *>(addr), len / sizeof(T)); // NOLINT
+ }
+
+public:
+ //! Default constructor
+ constexpr mapped() {} // NOLINT
+
+ //! Returns a reference to the internal section handle
+ const section_handle &section() const noexcept { return _sectionh; }
+ //! Returns a reference to the internal map handle
+ const map_handle &map() const noexcept { return _maph; }
+
+ /*! Create a view of newly allocated unused memory, creating new memory if insufficient unused memory is available.
+ Note that the memory mapped by this call may contain non-zero bits (recycled memory) unless `zeroed` is true.
+
+ \param length The number of items to map.
+ \param zeroed Whether to ensure that the viewed memory returned is all bits zero or not.
+ \param _flag The flags to pass to `map_handle::map()`.
+ */
+ explicit mapped(size_type length, bool zeroed = false, section_handle::flag _flag = section_handle::flag::readwrite)
+ : _maph(map_handle::map(length * sizeof(T), zeroed, _flag).value())
+ {
+ byte *addr = _maph.address();
+ static_cast<span<T> &>(*this) = span<T>(reinterpret_cast<T *>(addr), length); // NOLINT
+ }
+ /*! Construct a mapped view of the given section handle.
+
+ \param sh The section handle to use as the data source for creating the map.
+ \param length The number of items to map, use -1 to mean the length of the section handle divided by `sizeof(T)`.
+ \param byteoffset The byte offset into the section handle, this does not need to be a multiple of the page size.
+ \param _flag The flags to pass to `map_handle::map()`.
+ */
+ explicit mapped(section_handle &sh, size_type length = (size_type) -1, extent_type byteoffset = 0, section_handle::flag _flag = section_handle::flag::readwrite) // NOLINT
+ : mapped((length == 0) ? mapped() : mapped(nullptr, 0,
+#ifdef _WIN32
+ byteoffset & ~65535,
+#else
+ utils::round_down_to_page_size(byteoffset),
+#endif
+ byteoffset, &sh, (length == (size_type) -1) ? 0 : length * sizeof(T), _flag)) // NOLINT
+ {
+ }
+ /*! Construct a mapped view of the given file.
+
+ \param backing The handle to use as backing storage.
+ \param length The number of items to map, use -1 to mean the length of the section handle divided by `sizeof(T)`.
+ \param maximum_size The initial size of this section *in bytes*, which cannot be larger than any backing file. Zero means to use `backing.maximum_extent()`.
+ \param byteoffset The byte offset into the section handle, this does not need to be a multiple of the page size.
+ \param _flag The flags to pass to `map_handle::map()`.
+ */
+ explicit mapped(file_handle &backing, size_type length = (size_type) -1, extent_type maximum_size = 0, extent_type byteoffset = 0, section_handle::flag _flag = section_handle::flag::readwrite) // NOLINT
+ : mapped((length == 0) ? mapped() : mapped(&backing, maximum_size,
+#ifdef _WIN32
+ byteoffset & ~65535,
+#else
+ utils::round_down_to_page_size(byteoffset),
+#endif
+ byteoffset, nullptr, (length == (size_type) -1) ? 0 : length * sizeof(T), _flag)) // NOLINT
+ {
+ }
+};
+
+LLFIO_V2_NAMESPACE_END
+
+#endif
diff --git a/include/afio/v2.0/mapped_file_handle.hpp b/include/llfio/v2.0/mapped_file_handle.hpp
index 37c0b49b..97be4dde 100644
--- a/include/afio/v2.0/mapped_file_handle.hpp
+++ b/include/llfio/v2.0/mapped_file_handle.hpp
@@ -26,10 +26,10 @@ Distributed under the Boost Software License, Version 1.0.
//! \file mapped_file_handle.hpp Provides mapped_file_handle
-#ifndef AFIO_MAPPED_FILE_HANDLE_H
-#define AFIO_MAPPED_FILE_HANDLE_H
+#ifndef LLFIO_MAPPED_FILE_HANDLE_H
+#define LLFIO_MAPPED_FILE_HANDLE_H
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
/*! \class mapped_file_handle
\brief A memory mapped regular file or device
@@ -104,7 +104,7 @@ mixing mapped and normal i/o is generally safe except at the end of a file where
conditions and outright kernel bugs tend to abound. To avoid these, solely and exclusively
use a dedicated handle configured to atomic append only to do the appends.
*/
-class AFIO_DECL mapped_file_handle : public file_handle
+class LLFIO_DECL mapped_file_handle : public file_handle
{
public:
using dev_t = file_handle::dev_t;
@@ -163,7 +163,7 @@ public:
//! No copy assignment
mapped_file_handle &operator=(const mapped_file_handle &) = delete;
//! Swap with another instance
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
void swap(mapped_file_handle &o) noexcept
{
mapped_file_handle temp(std::move(*this));
@@ -185,7 +185,7 @@ public:
\errors Any of the values which the constructors for `file_handle`, `section_handle` and `map_handle` can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<mapped_file_handle> mapped_file(size_type reservation, const path_handle &base, path_view_type _path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept
{
if(_mode == mode::append)
@@ -212,7 +212,7 @@ public:
}
}
//! \overload
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<mapped_file_handle> mapped_file(const path_handle &base, path_view_type _path, mode _mode = mode::read, creation _creation = creation::open_existing, caching _caching = caching::all, flag flags = flag::none) noexcept { return mapped_file(0, base, _path, _mode, _creation, _caching, flags); }
/*! Create an mapped file handle creating a randomly named file on a path.
@@ -223,7 +223,7 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<mapped_file_handle> mapped_random_file(size_type reservation, const path_handle &dirpath, mode _mode = mode::write, caching _caching = caching::temporary, flag flags = flag::none) noexcept
{
try
@@ -259,7 +259,7 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
+ LLFIO_MAKE_FREE_FUNCTION
static inline result<mapped_file_handle> mapped_temp_file(size_type reservation, path_view_type name = path_view_type(), mode _mode = mode::write, creation _creation = creation::if_needed, caching _caching = caching::temporary, flag flags = flag::unlink_on_first_close) noexcept
{
auto &tempdirh = path_discovery::storage_backed_temporary_files_directory();
@@ -275,8 +275,8 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<mapped_file_handle> mapped_temp_inode(const path_handle &dir = path_discovery::storage_backed_temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<mapped_file_handle> mapped_temp_inode(const path_handle &dir = path_discovery::storage_backed_temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept
{
OUTCOME_TRY(v, file_handle::temp_inode(dir, _mode, flags));
mapped_file_handle ret(std::move(v));
@@ -309,19 +309,19 @@ public:
Note that this is an expensive call, and `address()` may return a different value afterwards.
This call will fail if the underlying file has zero length.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_type> reserve(size_type reservation = 0) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_type> reserve(size_type reservation = 0) noexcept;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~mapped_file_handle() override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~mapped_file_handle() override
{
if(_v)
{
(void) mapped_file_handle::close();
}
}
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override { return _mh.barrier(reqs, wait_for_device, and_metadata, d); }
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override { return _mh.barrier(reqs, wait_for_device, and_metadata, d); }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone(mode mode_ = mode::unchanged, caching caching_ = caching::unchanged, deadline d = std::chrono::seconds(30)) const noexcept override
{
OUTCOME_TRY(fh, file_handle::clone(mode_, caching_, d));
mapped_file_handle ret(std::move(fh), _reservation);
@@ -333,7 +333,7 @@ public:
return mapped_file_handle(std::move(fh), reservation);
}
//! Return the current maximum permitted extent of the file.
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> maximum_extent() const noexcept override { return _mh.length(); }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> maximum_extent() const noexcept override { return _mh.length(); }
/*! \brief Resize the current maximum permitted extent of the mapped file to the given extent, avoiding any
new allocation of physical storage where supported, and mapping or unmapping any new pages
@@ -356,7 +356,7 @@ public:
\param newsize The bytes to truncate the file to. Zero causes the maps to be closed before
truncation.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> truncate(extent_type newsize) noexcept override;
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> truncate(extent_type newsize) noexcept override;
/*! \brief Efficiently update the mapping to match that of the underlying file,
returning the size of the underlying file.
@@ -365,9 +365,9 @@ public:
If the internal section and map handle are invalid, they are restored unless the underlying file is zero length.
*/
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<extent_type> update_map() noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<extent_type> update_map() noexcept;
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> zero(extent_type offset, extent_type bytes, deadline /*unused*/ = deadline()) noexcept override
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<extent_type> zero(extent_type offset, extent_type bytes, deadline /*unused*/ = deadline()) noexcept override
{
OUTCOME_TRYV(_mh.zero_memory({_mh.address() + offset, bytes}));
return bytes;
@@ -389,7 +389,7 @@ public:
\errors None, though the various signals and structured exception throws common to using memory maps may occur.
\mallocs None.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override { return _mh.read(reqs, d); }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override { return _mh.read(reqs, d); }
/*! \brief Write data to the mapped file.
\note This call traps signals and structured exception throws using `QUICKCPPLIB_NAMESPACE::signal_guard`.
@@ -406,7 +406,7 @@ public:
of the raised signal, but it is by far the most likely.
\mallocs None if a `QUICKCPPLIB_NAMESPACE::signal_guard_install` is already instanced.
*/
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override { return _mh.write(reqs, d); }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override { return _mh.write(reqs, d); }
};
//! \brief Constructor for `mapped_file_handle`
@@ -504,16 +504,16 @@ inline result<mapped_file_handle> mapped_temp_inode(const path_handle &dir = pat
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/mapped_file_handle.ipp"
#else
#include "detail/impl/posix/mapped_file_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#endif
diff --git a/include/afio/v2.0/native_handle_type.hpp b/include/llfio/v2.0/native_handle_type.hpp
index 7c351f83..c4784f94 100644
--- a/include/afio/v2.0/native_handle_type.hpp
+++ b/include/llfio/v2.0/native_handle_type.hpp
@@ -22,17 +22,17 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_CONFIG_HPP
-#error You must include the master afio.hpp, not individual header files directly
+#ifndef LLFIO_CONFIG_HPP
+#error You must include the master llfio.hpp, not individual header files directly
#endif
#include "config.hpp"
//! \file native_handle_type.hpp Provides native_handle_type
-#ifndef AFIO_NATIVE_HANDLE_TYPE_H
-#define AFIO_NATIVE_HANDLE_TYPE_H
+#ifndef LLFIO_NATIVE_HANDLE_TYPE_H
+#define LLFIO_NATIVE_HANDLE_TYPE_H
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
/*! \struct native_handle_type
\brief A native handle type used for wrapping file descriptors, process ids or HANDLEs.
@@ -58,7 +58,9 @@ struct native_handle_type // NOLINT
symlink = 1U << 10U, //!< Is a symlink
multiplexer = 1U << 11U, //!< Is a kqueue/epoll/iocp
process = 1U << 12U, //!< Is a child process
- section = 1U << 13U //!< Is a memory section
+ section = 1U << 13U, //!< Is a memory section
+
+ _child_close_executed = 1U << 28U // used to trap when vptr has become corrupted
}
QUICKCPPLIB_BITFIELD_END(disposition)
disposition behaviour; //! The behaviour of the handle
@@ -141,7 +143,7 @@ struct native_handle_type // NOLINT
constexpr bool is_section() const noexcept { return (behaviour & disposition::section) ? true : false; }
};
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
#endif
diff --git a/include/llfio/v2.0/outcome b/include/llfio/v2.0/outcome
new file mode 160000
+Subproject 4499df4c41e85450b87a6b1338a755bbb5e2655
diff --git a/include/afio/v2.0/path_discovery.hpp b/include/llfio/v2.0/path_discovery.hpp
index ad6ee9fb..d6249140 100644
--- a/include/afio/v2.0/path_discovery.hpp
+++ b/include/llfio/v2.0/path_discovery.hpp
@@ -22,15 +22,15 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_PATH_DISCOVERY_H
-#define AFIO_PATH_DISCOVERY_H
+#ifndef LLFIO_PATH_DISCOVERY_H
+#define LLFIO_PATH_DISCOVERY_H
#include "fs_handle.hpp"
#include "stat.hpp"
//! \file path_discovery.hpp Provides `path_discovery`
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
//! \brief Contains functions used to discover suitable paths for things
namespace path_discovery
@@ -60,9 +60,9 @@ namespace path_discovery
static constexpr const char *values[] = {"local", "environment", "system", "hardcoded"};
if(static_cast<size_t>(v) >= sizeof(values) / sizeof(values[0]) || (values[static_cast<size_t>(v)] == nullptr))
{
- return s << "afio::path_discovery::discovered_path::source_type::<unknown>";
+ return s << "llfio::path_discovery::discovered_path::source_type::<unknown>";
}
- return s << "afio::path_discovery::discovered_path::source_type::" << values[static_cast<size_t>(v)];
+ return s << "llfio::path_discovery::discovered_path::source_type::" << values[static_cast<size_t>(v)];
}
/*! \brief Returns a list of potential directories which might be usuable for temporary files.
@@ -77,7 +77,7 @@ namespace path_discovery
may allocate additional memory for paths returned.
\errors This call never fails, except to return an empty span.
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC span<discovered_path> all_temporary_directories(bool refresh = false) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC span<discovered_path> all_temporary_directories(bool refresh = false) noexcept;
/*! \brief Returns a subset of `all_temporary_directories()` each of which has been tested to be writable
by the current process. No testing is done of available writable space.
@@ -91,7 +91,7 @@ namespace path_discovery
\errors This call never fails, though if it fails to find any writable temporary directory, it will
terminate the process.
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC span<discovered_path> verified_temporary_directories() noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC span<discovered_path> verified_temporary_directories() noexcept;
/*! \brief Returns a reference to an open handle to a verified temporary directory where files created are
stored in a filesystem directory, usually under the current user's quota.
@@ -103,7 +103,7 @@ namespace path_discovery
The handle is created during `verified_temporary_directories()` and is statically cached thereafter.
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC const path_handle &storage_backed_temporary_files_directory() noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC const path_handle &storage_backed_temporary_files_directory() noexcept;
/*! \brief Returns a reference to an open handle to a verified temporary directory where files created are
stored in memory/paging file, and thus access may be a lot quicker, but stronger limits on
@@ -120,10 +120,10 @@ namespace path_discovery
the same extent into multiple addresses e.g. to implement a constant time zero copy `realloc()`,
strongly consider using a non-file-backed `section_handle` as this is more portable.
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC const path_handle &memory_backed_temporary_files_directory() noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC const path_handle &memory_backed_temporary_files_directory() noexcept;
} // namespace path_discovery
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// .ipp is included by file_handle.hpp if in header only mode
diff --git a/include/afio/v2.0/path_handle.hpp b/include/llfio/v2.0/path_handle.hpp
index b759fb1d..1e308ca7 100644
--- a/include/afio/v2.0/path_handle.hpp
+++ b/include/llfio/v2.0/path_handle.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_PATH_HANDLE_H
-#define AFIO_PATH_HANDLE_H
+#ifndef LLFIO_PATH_HANDLE_H
+#define LLFIO_PATH_HANDLE_H
#include "handle.hpp"
#include "path_view.hpp"
@@ -35,7 +35,7 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
class directory_handle;
@@ -46,7 +46,7 @@ unpredictably relocate over time. This handle is thus an *anchor* to a subset is
filing system, free of any race conditions introduced by third party changes to any part
of the path leading to that island.
*/
-class AFIO_DECL path_handle : public handle
+class LLFIO_DECL path_handle : public handle
{
friend class directory_handle;
@@ -64,7 +64,6 @@ public:
//! Default constructor
constexpr path_handle() {} // NOLINT
- ~path_handle() = default;
//! Construct a handle from a supplied native handle
explicit constexpr path_handle(native_handle_type h, caching caching = caching::all, flag flags = flag::none)
: handle(h, caching, flags)
@@ -77,9 +76,22 @@ public:
//! No copy construction (use `clone()`)
path_handle(const path_handle &) = delete;
//! Move assignment permitted
- path_handle &operator=(path_handle &&) = default;
+ path_handle &operator=(path_handle &&o) noexcept
+ {
+ this->~path_handle();
+ new(this) path_handle(std::move(o));
+ return *this;
+ }
//! No copy assignment
path_handle &operator=(const path_handle &) = delete;
+ //! Swap with another instance
+ LLFIO_MAKE_FREE_FUNCTION
+ void swap(path_handle &o) noexcept
+ {
+ path_handle temp(std::move(*this));
+ *this = std::move(o);
+ o = std::move(temp);
+ }
/*! Create a path handle opening access to some location on the filing system.
Some operating systems provide a particularly lightweight method of doing this
@@ -88,11 +100,40 @@ public:
\errors Any of the values POSIX open() or CreateFile() can return.
*/
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> path(const path_handle &base, path_view_type path) noexcept;
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> path(const path_handle &base, path_view_type path) noexcept;
//! \overload
- AFIO_MAKE_FREE_FUNCTION
- static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> path(path_view_type _path) noexcept { return path(path_handle(), _path); }
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> path(path_view_type _path) noexcept { return path(path_handle(), _path); }
+
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~path_handle() override
+ {
+ if(_v)
+ {
+ (void) path_handle::close();
+ }
+ }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
+ {
+ LLFIO_LOG_FUNCTION_CALL(this);
+#ifndef NDEBUG
+ if(_v)
+ {
+ // Tell handle::close() that we have correctly executed
+ _v.behaviour |= native_handle_type::disposition::_child_close_executed;
+ }
+#endif
+ return handle::close();
+ }
+ /*! Clone this handle (copy constructor is disabled to avoid accidental copying).
+ */
+ result<path_handle> clone() const noexcept
+ {
+ auto *h = static_cast<const handle *>(this);
+ OUTCOME_TRY(ret, h->clone());
+ auto nativeh = ret.release();
+ return path_handle(nativeh);
+ }
};
//! \brief Constructor for `path_handle`
@@ -122,16 +163,16 @@ inline result<path_handle> path(path_handle::path_view_type _path) noexcept
}
// END make_free_functions.py
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/path_handle.ipp"
#else
#include "detail/impl/posix/path_handle.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/path_view.hpp b/include/llfio/v2.0/path_view.hpp
index ba81c695..73faec7a 100644
--- a/include/afio/v2.0/path_view.hpp
+++ b/include/llfio/v2.0/path_view.hpp
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_PATH_VIEW_H
-#define AFIO_PATH_VIEW_H
+#ifndef LLFIO_PATH_VIEW_H
+#define LLFIO_PATH_VIEW_H
#include "config.hpp"
@@ -34,7 +34,7 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
@@ -55,9 +55,9 @@ namespace detail
\brief A borrowed view of a path. A lightweight trivial-type alternative to
`std::filesystem::path`.
-AFIO is sufficiently fast that `std::filesystem::path` as a wrapper of an
+LLFIO is sufficiently fast that `std::filesystem::path` as a wrapper of an
underlying `std::basic_string<>` can be problematically expensive for some
-filing system operations due to the potential memory allocation. AFIO
+filing system operations due to the potential memory allocation. LLFIO
therefore works exclusively with borrowed views of other path storage.
Some of the API for `std::filesystem::path` is replicated here, however any
@@ -70,7 +70,7 @@ possible with borrowed views.
Be aware that on Microsoft Windows, the native path storage
`std::filesystem::path::value_type` is a `wchar_t` referring to UTF-16.
-However much of AFIO path usage is a `path_handle` to somewhere on the filing
+However much of LLFIO path usage is a `path_handle` to somewhere on the filing
system plus a relative `const char *` UTF-8 path fragment as the use of
absolute paths is discouraged. Rather than complicate the ABI to handle
templated path character types, on Microsoft Windows only we do the following:
@@ -85,12 +85,12 @@ buffer. We use the fast NT kernel UTF8 to UTF16 routine, not the slow Win32
routine.
3. Any forward slashes are converted to backwards slashes.
-AFIO calls the NT kernel API directly rather than the Win32 API for:
+LLFIO calls the NT kernel API directly rather than the Win32 API for:
- For any paths relative to a `path_handle` (the Win32 API does not provide a
race free file system API).
- For any paths beginning with `\!!\`, we pass the path + 3 characters
-directly through. This prefix is a pure AFIO extension, and will not be
+directly through. This prefix is a pure LLFIO extension, and will not be
recognised by other code.
- For any paths beginning with `\??\`, we pass the path + 0 characters
directly through. Note the NT kernel keeps a symlink at `\??\` which refers to
@@ -119,19 +119,9 @@ routine.
If however you are taking input from some external piece of code, then for
maximum compatibility you should still use the Win32 API.
*/
-class AFIO_DECL path_view
+class LLFIO_DECL path_view
{
public:
- //! Character type
- using value_type = char;
- //! Pointer type
- using pointer = char *;
- //! Const pointer type
- using const_pointer = const char *;
- //! Reference type
- using reference = char &;
- //! Const reference type
- using const_reference = const char &;
// const_iterator
// iterator
// reverse_iterator
@@ -141,6 +131,9 @@ public:
//! Difference type
using difference_type = std::ptrdiff_t;
+ //! The preferred separator type
+ static constexpr auto preferred_separator = filesystem::path::preferred_separator;
+
private:
static constexpr auto _npos = string_view::npos;
#ifdef _WIN32
@@ -167,6 +160,16 @@ private:
} _state;
template <class U> constexpr auto _invoke(U &&f) noexcept { return !_state._utf16.empty() ? f(_state._utf16) : f(_state._utf8); }
template <class U> constexpr auto _invoke(U &&f) const noexcept { return !_state._utf16.empty() ? f(_state._utf16) : f(_state._utf8); }
+ constexpr auto _find_first_sep(size_t startidx = 0) const noexcept
+ {
+ // wchar paths must use backslashes
+ if(!_state._utf16.empty())
+ {
+ return _state._utf16.find('\\', startidx);
+ }
+ // char paths can use either
+ return _state._utf8.find_first_of("/\\", startidx);
+ }
constexpr auto _find_last_sep() const noexcept
{
// wchar paths must use backslashes
@@ -191,7 +194,8 @@ private:
} _state;
template <class U> constexpr auto _invoke(U &&f) noexcept { return f(_state._utf8); }
template <class U> constexpr auto _invoke(U &&f) const noexcept { return f(_state._utf8); }
- constexpr auto _find_last_sep() const noexcept { return _state._utf8.rfind(filesystem::path::preferred_separator); }
+ constexpr auto _find_first_sep(size_t startidx = 0) const noexcept { return _state._utf8.find(preferred_separator, startidx); }
+ constexpr auto _find_last_sep() const noexcept { return _state._utf8.rfind(preferred_separator); }
#endif
public:
//! Constructs an empty path view
@@ -252,16 +256,38 @@ public:
{
return _invoke([](const auto &v) { return v.empty(); });
}
- constexpr bool has_root_path() const noexcept;
- constexpr bool has_root_name() const noexcept;
- constexpr bool has_root_directory() const noexcept;
- constexpr bool has_relative_path() const noexcept;
- constexpr bool has_parent_path() const noexcept;
- constexpr bool has_filename() const noexcept;
- constexpr bool has_stem() const noexcept;
- constexpr bool has_extension() const noexcept;
- constexpr bool is_absolute() const noexcept;
- constexpr bool is_relative() const noexcept;
+ constexpr bool has_root_path() const noexcept { return !root_path().empty(); }
+ constexpr bool has_root_name() const noexcept { return !root_name().empty(); }
+ constexpr bool has_root_directory() const noexcept { return !root_directory().empty(); }
+ constexpr bool has_relative_path() const noexcept { return !relative_path().empty(); }
+ constexpr bool has_parent_path() const noexcept { return !parent_path().empty(); }
+ constexpr bool has_filename() const noexcept { return !filename().empty(); }
+ constexpr bool has_stem() const noexcept { return !stem().empty(); }
+ constexpr bool has_extension() const noexcept { return !extension().empty(); }
+ constexpr bool is_absolute() const noexcept
+ {
+ auto sep_idx = _find_first_sep();
+ if(_npos == sep_idx)
+ {
+ return false;
+ }
+#ifdef _WIN32
+ if(is_ntpath())
+ return true;
+ return _invoke([sep_idx](const auto &v) {
+ if(sep_idx == 0)
+ {
+ if(v[sep_idx + 1] == preferred_separator) // double separator at front
+ return true;
+ }
+ auto colon_idx = v.find(':');
+ return colon_idx < sep_idx; // colon before first separator
+ });
+#else
+ return sep_idx == 0;
+#endif
+ }
+ constexpr bool is_relative() const noexcept { return !is_absolute(); }
// True if the path view contains any of the characters `*`, `?`, (POSIX only: `[` or `]`).
constexpr bool contains_glob() const noexcept
{
@@ -300,8 +326,8 @@ public:
return false;
});
}
- // True if the path view matches the format of an AFIO deleted file
- constexpr bool is_afio_deleted() const noexcept
+ // True if the path view matches the format of an LLFIO deleted file
+ constexpr bool is_llfio_deleted() const noexcept
{
return filename()._invoke([](const auto &v) {
if(v.size() == 64 + 8)
@@ -342,11 +368,109 @@ public:
{
return _invoke([](const auto &v) { return v.size(); });
}
- constexpr path_view root_name() const noexcept;
- constexpr path_view root_directory() const noexcept;
- constexpr path_view root_path() const noexcept;
- constexpr path_view relative_path() const noexcept;
- constexpr path_view parent_path() const noexcept;
+ //! Returns a view of the root name part of this view e.g. C:
+ constexpr path_view root_name() const noexcept
+ {
+ auto sep_idx = _find_first_sep();
+ if(_npos == sep_idx)
+ {
+ return path_view();
+ }
+ return _invoke([sep_idx](const auto &v) { return path_view(v.data(), sep_idx); });
+ }
+ //! Returns a view of the root directory, if there is one e.g. /
+ constexpr path_view root_directory() const noexcept
+ {
+ auto sep_idx = _find_first_sep();
+ if(_npos == sep_idx)
+ {
+ return path_view();
+ }
+ return _invoke([sep_idx](const auto &v) {
+#ifdef _WIN32
+ auto colon_idx = v.find(':');
+ if(colon_idx < sep_idx)
+ {
+ return path_view(v.data() + sep_idx, 1);
+ }
+#endif
+ if(sep_idx == 0)
+ {
+ return path_view(v.data(), 1);
+ }
+ return path_view();
+ });
+ }
+ //! Returns, if any, a view of the root path part of this view e.g. C:/
+ constexpr path_view root_path() const noexcept
+ {
+ auto sep_idx = _find_first_sep();
+ if(_npos == sep_idx)
+ {
+ return path_view();
+ }
+ return _invoke([this, sep_idx](const auto &v) {
+#ifdef _WIN32
+ if(is_ntpath())
+ {
+ return path_view(v.data() + 3, 1);
+ }
+ // Special case \\.\ and \\?\ to match filesystem::path
+ if(v.size() >= 4 && sep_idx == 0 && v[1] == '\\' && (v[2] == '.' || v[2] == '?') && v[3] == '\\')
+ {
+ return path_view(v.data() + 0, 4);
+ }
+ auto colon_idx = v.find(':');
+ if(colon_idx < sep_idx)
+ {
+ return path_view(v.data(), sep_idx + 1);
+ }
+#endif
+ if(sep_idx == 0)
+ {
+ return path_view(v.data(), 1);
+ }
+ return path_view();
+ });
+ }
+ //! Returns a view of everything after the root path
+ constexpr path_view relative_path() const noexcept
+ {
+ auto sep_idx = _find_first_sep();
+ if(_npos == sep_idx)
+ {
+ return *this;
+ }
+ return _invoke([this, sep_idx](const auto &v) {
+#ifdef _WIN32
+ // Special case \\.\ and \\?\ to match filesystem::path
+ if(v.size() >= 4 && sep_idx == 0 && v[1] == '\\' && (v[2] == '.' || v[2] == '?') && v[3] == '\\')
+ {
+ return path_view(v.data() + 4, v.size() - 4);
+ }
+ auto colon_idx = v.find(':');
+ if(colon_idx < sep_idx)
+ {
+ return path_view(v.data() + sep_idx + 1, v.size() - sep_idx - 1);
+ }
+#endif
+ if(sep_idx == 0)
+ {
+ return path_view(v.data() + 1, v.size() - 1);
+ }
+ return path_view(v.data(), v.size());
+ });
+ }
+ //! Returns a view of the everything apart from the filename part of this view
+ constexpr path_view parent_path() const noexcept
+ {
+ auto sep_idx = _find_last_sep();
+ if(_npos == sep_idx)
+ {
+ return path_view();
+ }
+ return _invoke([sep_idx](const auto &v) { return path_view(v.data(), sep_idx); });
+ }
//! Returns a view of the filename part of this view.
constexpr path_view filename() const noexcept
{
@@ -357,8 +481,32 @@ public:
}
return _invoke([sep_idx](const auto &v) { return path_view(v.data() + sep_idx + 1, v.size() - sep_idx - 1); });
}
- constexpr path_view stem() const noexcept;
- constexpr path_view extension() const noexcept;
+ //! Returns a view of the filename without any file extension
+ constexpr path_view stem() const noexcept
+ {
+ auto sep_idx = _find_last_sep();
+ return _invoke([sep_idx](const auto &v) {
+ auto dot_idx = v.rfind('.');
+ if(_npos == dot_idx || (_npos != sep_idx && dot_idx < sep_idx) || dot_idx == sep_idx + 1 || (dot_idx == sep_idx + 2 && v[dot_idx - 1] == '.'))
+ {
+ return path_view(v.data() + sep_idx + 1, v.size() - sep_idx - 1);
+ }
+ return path_view(v.data() + sep_idx + 1, dot_idx - sep_idx - 1);
+ });
+ }
+ //! Returns a view of the file extension part of this view
+ constexpr path_view extension() const noexcept
+ {
+ auto sep_idx = _find_last_sep();
+ return _invoke([sep_idx](const auto &v) {
+ auto dot_idx = v.rfind('.');
+ if(_npos == dot_idx || (_npos != sep_idx && dot_idx < sep_idx) || dot_idx == sep_idx + 1 || (dot_idx == sep_idx + 2 && v[dot_idx - 1] == '.'))
+ {
+ return path_view();
+ }
+ return path_view(v.data() + dot_idx, v.size() - dot_idx);
+ });
+ }
//! Return the path view as a path.
filesystem::path path() const
@@ -423,7 +571,7 @@ public:
// iterator end() const;
//! Instantiate from a `path_view` to get a zero terminated path suitable for feeding to the kernel
- struct AFIO_DECL c_str
+ struct LLFIO_DECL c_str
{
//! Number of characters, excluding zero terminating char, at buffer
uint16_t length{0};
@@ -436,7 +584,7 @@ public:
{
if(view._state._utf16.size() > 32768)
{
- AFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 64Kb to kernel");
+ LLFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 64Kb to kernel");
abort();
}
length = static_cast<uint16_t>(view._state._utf16.size());
@@ -455,7 +603,7 @@ public:
// Otherwise use _buffer and zero terminate.
if(length > sizeof(_buffer) - 1)
{
- AFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 64Kb to kernel");
+ LLFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 64Kb to kernel");
abort();
}
memcpy(_buffer, view._state._utf16.data(), length);
@@ -475,7 +623,7 @@ public:
{
if(view._state._utf8.size() > 32768)
{
- AFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 64Kb to kernel");
+ LLFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 64Kb to kernel");
abort();
}
length = static_cast<uint16_t>(view._state._utf8.size());
@@ -488,7 +636,7 @@ public:
// Otherwise use _buffer and zero terminate.
if(length > sizeof(_buffer) - 1)
{
- AFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 32Kb to kernel");
+ LLFIO_LOG_FATAL(&view, "Attempt to send a path exceeding 32Kb to kernel");
abort();
}
memcpy(_buffer, view._state._utf8.data(), length);
@@ -510,7 +658,7 @@ public:
private:
filesystem::path::value_type _buffer[32768]{};
#ifdef _WIN32
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC void _from_utf8(const path_view &view) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void _from_utf8(const path_view &view) noexcept;
#endif
};
friend struct c_str;
@@ -556,14 +704,14 @@ inline std::ostream &operator<<(std::ostream &s, const path_view &v)
static_assert(std::is_trivially_copyable<path_view>::value, "path_view is not a trivially copyable!");
#endif
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/path_view.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/llfio/v2.0/quickcpplib b/include/llfio/v2.0/quickcpplib
new file mode 160000
+Subproject 0c2e5dd3102d865e4728c4af0c54456e3ef27f1
diff --git a/include/afio/v2.0/stat.hpp b/include/llfio/v2.0/stat.hpp
index c8cd5d4d..4ffee773 100644
--- a/include/afio/v2.0/stat.hpp
+++ b/include/llfio/v2.0/stat.hpp
@@ -22,11 +22,11 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_STAT_H
-#define AFIO_STAT_H
+#ifndef LLFIO_STAT_H
+#define LLFIO_STAT_H
-#ifndef AFIO_CONFIG_HPP
-#error You must include the master afio.hpp, not individual header files directly
+#ifndef LLFIO_CONFIG_HPP
+#error You must include the master llfio.hpp, not individual header files directly
#endif
#include "config.hpp"
@@ -37,7 +37,7 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
class handle;
@@ -148,19 +148,19 @@ struct stat_t // NOLINT
}
#endif
//! Fills in the structure with metadata, returning number of items filled in
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> fill(const handle &h, want wanted = want::all) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> fill(const handle &h, want wanted = want::all) noexcept;
};
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/stat.ipp"
#else
#include "detail/impl/posix/stat.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/statfs.hpp b/include/llfio/v2.0/statfs.hpp
index 7f0ae23b..71732da5 100644
--- a/include/afio/v2.0/statfs.hpp
+++ b/include/llfio/v2.0/statfs.hpp
@@ -22,11 +22,11 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_STATFS_H
-#define AFIO_STATFS_H
+#ifndef LLFIO_STATFS_H
+#define LLFIO_STATFS_H
-#ifndef AFIO_CONFIG_HPP
-#error You must include the master afio.hpp, not individual header files directly
+#ifndef LLFIO_CONFIG_HPP
+#error You must include the master llfio.hpp, not individual header files directly
#endif
#include "config.hpp"
@@ -37,14 +37,14 @@ Distributed under the Boost Software License, Version 1.0.
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
class handle;
/*! \struct statfs_t
\brief Metadata about a filing system. Unsupported entries are all bits set.
*/
-struct AFIO_DECL statfs_t
+struct LLFIO_DECL statfs_t
{
static constexpr uint32_t _allbits1_32 = ~0U;
static constexpr uint64_t _allbits1_64 = ~0ULL;
@@ -93,19 +93,19 @@ struct AFIO_DECL statfs_t
}
#endif
//! Fills in the structure with metadata, returning number of items filled in
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> fill(const handle &h, want wanted = want::all) noexcept;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<size_t> fill(const handle &h, want wanted = want::all) noexcept;
};
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/statfs.ipp"
#else
#include "detail/impl/posix/statfs.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/afio/v2.0/status_code.hpp b/include/llfio/v2.0/status_code.hpp
index 14b089f1..79edcde4 100644
--- a/include/afio/v2.0/status_code.hpp
+++ b/include/llfio/v2.0/status_code.hpp
@@ -1,4 +1,4 @@
-/* Configures AFIO
+/* LLFIO error handling
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: June 2018
@@ -22,8 +22,8 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_STATUS_CODE_HPP
-#define AFIO_STATUS_CODE_HPP
+#ifndef LLFIO_STATUS_CODE_HPP
+#define LLFIO_STATUS_CODE_HPP
#include "logging.hpp"
@@ -35,36 +35,36 @@ tag.
Status code, on the other hand, is templated and is designed for custom
domains which can set arbitrary payloads. So we define custom domains and
-status codes for AFIO with these combinations:
+status codes for LLFIO with these combinations:
- win32_error{ DWORD }
- ntkernel_error{ LONG }
- posix_error{ int }
- generic_error{ errc }
-Each of these is a separate AFIO custom status code domain. We also define
+Each of these is a separate LLFIO custom status code domain. We also define
an erased form of these custom domains, and that is typedefed to
-error_domain<intptr_t>::value_type.
+file_io_error_domain<intptr_t>::value_type.
-This design ensure that AFIO can be configured into either std-based error
+This design ensure that LLFIO can be configured into either std-based error
handling or SG14 experimental status code handling. It defaults to the latter
-as that (a) enables safe header only AFIO on Windows (b) produces better codegen
+as that (a) enables safe header only LLFIO on Windows (b) produces better codegen
(c) drags in far fewer STL headers.
*/
-#if AFIO_EXPERIMENTAL_STATUS_CODE
+#if LLFIO_EXPERIMENTAL_STATUS_CODE
// Bring in a result implementation based on status_code
#include "outcome/include/outcome/experimental/status_result.hpp"
#include "outcome/include/outcome/try.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
namespace detail
{
- template <class T> struct error_domain_value_type
+ template <class T> struct file_io_error_value_type
{
//! \brief The type of code
T sc{};
@@ -73,14 +73,14 @@ namespace detail
uint32_t _thread_id{0};
// The TLS path store entry
uint16_t _tls_path_id1{static_cast<uint16_t>(-1)}, _tls_path_id2{static_cast<uint16_t>(-1)};
- // The id of the relevant log entry in the AFIO log (if logging enabled)
+ // The id of the relevant log entry in the LLFIO log (if logging enabled)
size_t _log_id{static_cast<size_t>(-1)};
//! Default construction
- error_domain_value_type() = default;
+ file_io_error_value_type() = default;
//! Implicitly constructs an instance
- constexpr inline error_domain_value_type(T _sc)
+ constexpr inline file_io_error_value_type(T _sc)
: sc(_sc)
{
} // NOLINT
@@ -90,15 +90,15 @@ namespace detail
};
}
-template <class BaseStatusCodeDomain> class error_domain;
+template <class BaseStatusCodeDomain> class file_io_error_domain;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
// Inject a mixin for our custom status codes
SYSTEM_ERROR2_NAMESPACE_BEGIN
namespace mixins
{
- template <class Base, class BaseStatusCodeDomain> struct mixin<Base, ::AFIO_V2_NAMESPACE::error_domain<BaseStatusCodeDomain>> : public Base
+ template <class Base, class BaseStatusCodeDomain> struct mixin<Base, ::LLFIO_V2_NAMESPACE::file_io_error_domain<BaseStatusCodeDomain>> : public Base
{
using Base::Base;
@@ -107,7 +107,7 @@ namespace mixins
{
if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == this->value()._thread_id)
{
- auto &tls = ::AFIO_V2_NAMESPACE::detail::tls_errored_results();
+ auto &tls = ::LLFIO_V2_NAMESPACE::detail::tls_errored_results();
const char *path1 = tls.get(this->value()._tls_path_id1);
const char *path2 = tls.get(this->value()._tls_path_id2);
return {path1, path2};
@@ -115,29 +115,29 @@ namespace mixins
return {};
}
//! Retrieve the first path associated with this failure
- ::AFIO_V2_NAMESPACE::filesystem::path path1() const
+ ::LLFIO_V2_NAMESPACE::filesystem::path path1() const
{
if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == this->value()._thread_id)
{
- auto &tls = ::AFIO_V2_NAMESPACE::detail::tls_errored_results();
+ auto &tls = ::LLFIO_V2_NAMESPACE::detail::tls_errored_results();
const char *path1 = tls.get(this->value()._tls_path_id1);
if(path1 != nullptr)
{
- return ::AFIO_V2_NAMESPACE::filesystem::path(path1);
+ return ::LLFIO_V2_NAMESPACE::filesystem::path(path1);
}
}
return {};
}
//! Retrieve the second path associated with this failure
- ::AFIO_V2_NAMESPACE::filesystem::path path2() const
+ ::LLFIO_V2_NAMESPACE::filesystem::path path2() const
{
if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == this->value()._thread_id)
{
- auto &tls = ::AFIO_V2_NAMESPACE::detail::tls_errored_results();
+ auto &tls = ::LLFIO_V2_NAMESPACE::detail::tls_errored_results();
const char *path2 = tls.get(this->value()._tls_path_id2);
if(path2 != nullptr)
{
- return ::AFIO_V2_NAMESPACE::filesystem::path(path2);
+ return ::LLFIO_V2_NAMESPACE::filesystem::path(path2);
}
}
return {};
@@ -146,35 +146,35 @@ namespace mixins
}
SYSTEM_ERROR2_NAMESPACE_END
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
-/*! \class error_domain
-\brief The SG14 status code domain for errors in AFIO.
+/*! \class file_io_error_domain
+\brief The SG14 status code domain for errors in LLFIO.
*/
-template <class BaseStatusCodeDomain> class error_domain : public BaseStatusCodeDomain
+template <class BaseStatusCodeDomain> class file_io_error_domain : public BaseStatusCodeDomain
{
- friend class SYSTEM_ERROR2_NAMESPACE::status_code<error_domain>;
+ friend class SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain>;
using _base = BaseStatusCodeDomain;
public:
using string_ref = typename BaseStatusCodeDomain::string_ref;
using atomic_refcounted_string_ref = typename BaseStatusCodeDomain::atomic_refcounted_string_ref;
- //! \brief The value type of errors in AFIO
- using value_type = detail::error_domain_value_type<typename _base::value_type>;
+ //! \brief The value type of errors in LLFIO
+ using value_type = detail::file_io_error_value_type<typename _base::value_type>;
- error_domain() = default;
- error_domain(const error_domain &) = default;
- error_domain(error_domain &&) = default;
- error_domain &operator=(const error_domain &) = default;
- error_domain &operator=(error_domain &&) = default;
- ~error_domain() = default;
+ file_io_error_domain() = default;
+ file_io_error_domain(const file_io_error_domain &) = default;
+ file_io_error_domain(file_io_error_domain &&) = default;
+ file_io_error_domain &operator=(const file_io_error_domain &) = default;
+ file_io_error_domain &operator=(file_io_error_domain &&) = default;
+ ~file_io_error_domain() = default;
protected:
virtual inline string_ref _do_message(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final
{
assert(code.domain() == *this);
- const auto &v = static_cast<const SYSTEM_ERROR2_NAMESPACE::status_code<error_domain> &>(code); // NOLINT
+ const auto &v = static_cast<const SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain> &>(code); // NOLINT
// Get the paths for this failure, if any, using the mixins from above
auto paths = v._paths();
// Get the base message for this failure
@@ -198,7 +198,7 @@ protected:
}
ret.append("]");
}
-#if AFIO_LOGGING_LEVEL >= 2
+#if LLFIO_LOGGING_LEVEL >= 2
if(v.value()._log_id != static_cast<uint32_t>(-1))
{
if(log().valid(v.value()._log_id))
@@ -224,20 +224,20 @@ protected:
}
};
-#else // AFIO_DISABLE_PATHS_IN_FAILURE_INFO
-template <class BaseStatusCodeDomain> using error_domain = BaseStatusCodeDomain;
-#endif // AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#else // LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
+template <class BaseStatusCodeDomain> using file_io_error_domain = BaseStatusCodeDomain;
+#endif // LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
namespace detail
{
- using error_domain_value_system_code = error_domain_value_type<SYSTEM_ERROR2_NAMESPACE::system_code::value_type>;
+ using file_io_error_domain_value_system_code = file_io_error_value_type<SYSTEM_ERROR2_NAMESPACE::system_code::value_type>;
}
//! An erased status code
-using error_code = SYSTEM_ERROR2_NAMESPACE::errored_status_code<SYSTEM_ERROR2_NAMESPACE::erased<detail::error_domain_value_system_code>>;
+using file_io_error = SYSTEM_ERROR2_NAMESPACE::errored_status_code<SYSTEM_ERROR2_NAMESPACE::erased<detail::file_io_error_domain_value_system_code>>;
-template <class T> using result = OUTCOME_V2_NAMESPACE::experimental::erased_result<T, error_code>;
+template <class T> using result = OUTCOME_V2_NAMESPACE::experimental::erased_result<T, file_io_error>;
using OUTCOME_V2_NAMESPACE::success;
using OUTCOME_V2_NAMESPACE::failure;
using OUTCOME_V2_NAMESPACE::in_place_type;
@@ -246,22 +246,22 @@ using OUTCOME_V2_NAMESPACE::in_place_type;
using SYSTEM_ERROR2_NAMESPACE::errc;
//! Helper for constructing an error code from an errc
-inline error_code generic_error(errc c);
+inline file_io_error generic_error(errc c);
#ifndef _WIN32
//! Helper for constructing an error code from a POSIX errno
-inline error_code posix_error(int c = errno);
+inline file_io_error posix_error(int c = errno);
#else
//! Helper for constructing an error code from a DWORD
-inline error_code win32_error(SYSTEM_ERROR2_NAMESPACE::win32::DWORD c = SYSTEM_ERROR2_NAMESPACE::win32::GetLastError());
+inline file_io_error win32_error(SYSTEM_ERROR2_NAMESPACE::win32::DWORD c = SYSTEM_ERROR2_NAMESPACE::win32::GetLastError());
//! Helper for constructing an error code from a NTSTATUS
-inline error_code ntkernel_error(SYSTEM_ERROR2_NAMESPACE::win32::NTSTATUS c);
+inline file_io_error ntkernel_error(SYSTEM_ERROR2_NAMESPACE::win32::NTSTATUS c);
#endif
namespace detail
{
- inline std::ostream &operator<<(std::ostream &s, const error_code &v) { return s << "afio::error_code(" << v.message().c_str() << ")"; }
+ inline std::ostream &operator<<(std::ostream &s, const file_io_error &v) { return s << "llfio::file_io_error(" << v.message().c_str() << ")"; }
}
-inline error_code error_from_exception(std::exception_ptr &&ep = std::current_exception(), error_code not_matched = generic_error(errc::resource_unavailable_try_again)) noexcept
+inline file_io_error error_from_exception(std::exception_ptr &&ep = std::current_exception(), file_io_error not_matched = generic_error(errc::resource_unavailable_try_again)) noexcept
{
if(!ep)
{
@@ -331,16 +331,16 @@ inline error_code error_from_exception(std::exception_ptr &&ep = std::current_ex
return not_matched;
}
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#else // AFIO_EXPERIMENTAL_STATUS_CODE
+#else // LLFIO_EXPERIMENTAL_STATUS_CODE
// Bring in a result implementation based on std::error_code
#include "outcome/include/outcome.hpp"
-AFIO_V2_NAMESPACE_BEGIN
+LLFIO_V2_NAMESPACE_BEGIN
namespace detail
{
@@ -352,7 +352,7 @@ struct error_info;
inline std::error_code make_error_code(error_info ei);
/*! \struct error_info
-\brief The cause of the failure of an operation in AFIO.
+\brief The cause of the failure of an operation in LLFIO.
*/
struct error_info
{
@@ -364,12 +364,12 @@ private:
// The error code for the failure
std::error_code ec;
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
// The id of the thread where this failure occurred
uint32_t _thread_id{0};
// The TLS path store entry
uint16_t _tls_path_id1{static_cast<uint16_t>(-1)}, _tls_path_id2{static_cast<uint16_t>(-1)};
- // The id of the relevant log entry in the AFIO log (if logging enabled)
+ // The id of the relevant log entry in the LLFIO log (if logging enabled)
size_t _log_id{static_cast<size_t>(-1)};
public:
@@ -395,7 +395,7 @@ public:
//! Retrieve any first path associated with this failure. Note this only works if called from the same thread as where the failure occurred.
inline filesystem::path path1() const
{
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == _thread_id)
{
auto &tls = detail::tls_errored_results();
@@ -411,7 +411,7 @@ public:
//! Retrieve any second path associated with this failure. Note this only works if called from the same thread as where the failure occurred.
inline filesystem::path path2() const
{
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == _thread_id)
{
auto &tls = detail::tls_errored_results();
@@ -428,7 +428,7 @@ public:
inline std::string message() const
{
std::string ret(ec.message());
-#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+#ifndef LLFIO_DISABLE_PATHS_IN_FAILURE_INFO
detail::append_path_info(*this, ret);
#endif
return ret;
@@ -451,25 +451,53 @@ OUTCOME_TEMPLATE(class ErrorCondEnum)
OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_error_condition_enum<ErrorCondEnum>::value))
inline bool operator==(const error_info &a, const ErrorCondEnum &b)
{
- return make_error_code(a) == std::error_condition(b);
+ auto _a = make_error_code(a);
+ auto _b = std::error_condition(b);
+#ifndef _WIN32
+ // Looks like libstdc++ doesn't map system category to generic category, which is a bug
+ if(_a.category() == std::system_category() && _b.category() == std::generic_category() && _a.value() == static_cast<int>(b))
+ return true;
+#endif
+ return _a == _b;
}
OUTCOME_TEMPLATE(class ErrorCondEnum)
OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_error_condition_enum<ErrorCondEnum>::value))
inline bool operator==(const ErrorCondEnum &a, const error_info &b)
{
- return std::error_condition(a) == make_error_code(b);
+ auto _a = std::error_condition(a);
+ auto _b = make_error_code(b);
+#ifndef _WIN32
+ // Looks like libstdc++ doesn't map system category to generic category, which is a bug
+ if(_a.category() == std::generic_category() && _b.category() == std::system_category() && _b.value() == static_cast<int>(a))
+ return true;
+#endif
+ return _a == _b;
}
OUTCOME_TEMPLATE(class ErrorCondEnum)
OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_error_condition_enum<ErrorCondEnum>::value))
inline bool operator!=(const error_info &a, const ErrorCondEnum &b)
{
- return make_error_code(a) != std::error_condition(b);
+ auto _a = make_error_code(a);
+ auto _b = std::error_condition(b);
+#ifndef _WIN32
+ // Looks like libstdc++ doesn't map system category to generic category, which is a bug
+ if(_a.category() == std::system_category() && _b.category() == std::generic_category() && _a.value() == static_cast<int>(b))
+ return false;
+#endif
+ return _a != _b;
}
OUTCOME_TEMPLATE(class ErrorCondEnum)
OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_error_condition_enum<ErrorCondEnum>::value))
inline bool operator!=(const ErrorCondEnum &a, const error_info &b)
{
- return std::error_condition(a) != make_error_code(b);
+ auto _a = std::error_condition(a);
+ auto _b = make_error_code(b);
+#ifndef _WIN32
+ // Looks like libstdc++ doesn't map system category to generic category, which is a bug
+ if(_a.category() == std::generic_category() && _b.category() == std::system_category() && _b.value() == static_cast<int>(a))
+ return false;
+#endif
+ return _a != _b;
}
#ifndef NDEBUG
// Is trivial in all ways, except default constructibility
@@ -479,9 +507,9 @@ inline std::ostream &operator<<(std::ostream &s, const error_info &v)
{
if(make_error_code(v))
{
- return s << "afio::error_info(" << v.message() << ")";
+ return s << "llfio::error_info(" << v.message() << ")";
}
- return s << "afio::error_info(null)";
+ return s << "llfio::error_info(null)";
}
// Tell Outcome that error_info is to be treated as an error_code
inline std::error_code make_error_code(error_info ei)
@@ -495,7 +523,7 @@ inline void outcome_throw_as_system_error_with_payload(const error_info &ei)
}
/*! \class error
-\brief The exception type synthesised and thrown when an `afio::result` or `afio::outcome` is no-value observed.
+\brief The exception type synthesised and thrown when an `llfio::result` or `llfio::outcome` is no-value observed.
*/
class error : public filesystem::filesystem_error
{
@@ -552,9 +580,9 @@ inline error_info posix_error(int c = errno)
}
#endif
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#endif // AFIO_EXPERIMENTAL_STATUS_CODE
+#endif // LLFIO_EXPERIMENTAL_STATUS_CODE
#endif
diff --git a/include/afio/v2.0/storage_profile.hpp b/include/llfio/v2.0/storage_profile.hpp
index 36d50749..9d1a3679 100644
--- a/include/afio/v2.0/storage_profile.hpp
+++ b/include/llfio/v2.0/storage_profile.hpp
@@ -22,16 +22,16 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_STORAGE_PROFILE_H
-#define AFIO_STORAGE_PROFILE_H
+#ifndef LLFIO_STORAGE_PROFILE_H
+#define LLFIO_STORAGE_PROFILE_H
#include "io_service.hpp"
-#if AFIO_EXPERIMENTAL_STATUS_CODE
+#if LLFIO_EXPERIMENTAL_STATUS_CODE
#include "outcome/include/outcome/experimental/status_outcome.hpp"
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
-template <class T> using outcome = OUTCOME_V2_NAMESPACE::experimental::erased_outcome<T, error_code>;
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
+template <class T> using outcome = OUTCOME_V2_NAMESPACE::experimental::erased_outcome<T, file_io_error>;
+LLFIO_V2_NAMESPACE_END
#endif
#include <regex>
@@ -43,7 +43,7 @@ AFIO_V2_NAMESPACE_END
#pragma warning(disable : 4251) // dll interface
#endif
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace storage_profile
{
@@ -167,11 +167,11 @@ namespace storage_profile
namespace system
{
// OS name, version
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> os(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> os(storage_profile &sp, file_handle &h) noexcept;
// CPU name, architecture, physical cores
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> cpu(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> cpu(storage_profile &sp, file_handle &h) noexcept;
// System memory quantity, in use, max and min bandwidth
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> mem(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> mem(storage_profile &sp, file_handle &h) noexcept;
#ifdef _WIN32
namespace windows
{
@@ -179,20 +179,20 @@ namespace storage_profile
namespace posix
{
#endif
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> _mem(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> _mem(storage_profile &sp, file_handle &h) noexcept;
}
// High resolution clock granularity
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> clock_granularity(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> yield_overhead(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> sleep_wake_overhead(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> drop_filesystem_cache_support(storage_profile &sp, file_handle & /*unused*/) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> clock_granularity(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> yield_overhead(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> sleep_wake_overhead(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> drop_filesystem_cache_support(storage_profile &sp, file_handle & /*unused*/) noexcept;
} // namespace system
namespace storage
{
// Device name, size, min i/o size
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> device(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> device(storage_profile &sp, file_handle &h) noexcept;
// FS name, config, size, in use
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> fs(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> fs(storage_profile &sp, file_handle &h) noexcept;
#ifdef _WIN32
namespace windows
{
@@ -200,43 +200,43 @@ namespace storage_profile
namespace posix
{
#endif
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> _device(storage_profile &sp, file_handle &h, const std::string &_mntfromname, const std::string &fstypename) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> _device(storage_profile &sp, file_handle &h, const std::string &_mntfromname, const std::string &fstypename) noexcept;
}
} // namespace storage
namespace concurrency
{
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> atomic_rewrite_quantum(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> atomic_rewrite_offset_boundary(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> atomic_rewrite_quantum(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> atomic_rewrite_offset_boundary(storage_profile &sp, file_handle &srch) noexcept;
}
namespace latency
{
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> read_nothing(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> write_nothing(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> read_qd1(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> write_qd1(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> read_qd16(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> write_qd16(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> readwrite_qd4(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> read_nothing(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> write_nothing(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> read_qd1(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> write_qd1(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> read_qd16(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> write_qd16(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> readwrite_qd4(storage_profile &sp, file_handle &srch) noexcept;
}
namespace response_time
{
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_racefree_0b(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_racefree_1b(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_racefree_4k(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_0b(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_1b(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_4k(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_1M(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_racefree_0b(storage_profile &sp, file_handle &srch) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_racefree_1b(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_racefree_4k(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_nonracefree_0b(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_nonracefree_1b(storage_profile &sp, file_handle &h) noexcept;
- AFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_nonracefree_4k(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_racefree_0b(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_racefree_1b(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_racefree_4k(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_0b(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_1b(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_4k(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_warm_nonracefree_1M(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_racefree_0b(storage_profile &sp, file_handle &srch) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_racefree_1b(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_racefree_4k(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_nonracefree_0b(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_nonracefree_1b(storage_profile &sp, file_handle &h) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC outcome<void> traversal_cold_nonracefree_4k(storage_profile &sp, file_handle &h) noexcept;
} // namespace response_time
//! A (possibly incomplet) profile of storage
- struct AFIO_DECL storage_profile
+ struct LLFIO_DECL storage_profile
{
//! The size type
using size_type = size_t;
@@ -276,9 +276,9 @@ namespace storage_profile
const_iterator end() const noexcept { return begin() + max_size(); }
//! Read the matching items in the storage profile from in as YAML
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC void read(std::istream &in, std::regex which = std::regex(".*"));
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void read(std::istream &in, std::regex which = std::regex(".*"));
//! Write the matching items from storage profile as YAML to out with the given indentation
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC void write(std::ostream &out, const std::regex &which = std::regex(".*"), size_t _indent = 0, bool invert_match = false) const;
+ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void write(std::ostream &out, const std::regex &which = std::regex(".*"), size_t _indent = 0, bool invert_match = false) const;
// System characteristics
item<std::string> os_name = {"system:os:name", &system::os}; // e.g. Microsoft Windows NT
@@ -395,12 +395,12 @@ namespace storage_profile
};
} // namespace storage_profile
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#include "detail/impl/storage_profile.ipp"
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
#ifdef _MSC_VER
diff --git a/include/llfio/v2.0/symlink_handle.hpp b/include/llfio/v2.0/symlink_handle.hpp
new file mode 100644
index 00000000..844afe51
--- /dev/null
+++ b/include/llfio/v2.0/symlink_handle.hpp
@@ -0,0 +1,494 @@
+/* A handle to a symbolic link
+(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
+File Created: Jul 2018
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef LLFIO_SYMLINK_HANDLE_H
+#define LLFIO_SYMLINK_HANDLE_H
+
+#include "handle.hpp"
+#include "path_view.hpp"
+
+//! \file symlink_handle.hpp Provides a handle to a symbolic link.
+
+#ifndef LLFIO_SYMLINK_HANDLE_IS_FAKED
+#if defined(_WIN32) || defined(__linux__)
+#define LLFIO_SYMLINK_HANDLE_IS_FAKED 0
+#else
+#define LLFIO_SYMLINK_HANDLE_IS_FAKED 1
+#endif
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4251) // dll interface
+#endif
+
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
+
+class symlink_handle;
+
+namespace detail
+{
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<void> stat_from_symlink(struct stat &s, const handle &h) noexcept;
+}
+
+/*! \class symlink_handle
+\brief A handle to an inode which redirects to a different path.
+
+Microsoft Windows and Linux provide the ability to open the contents of a symbolic link directly,
+for those platforms this handle works exactly like any ordinary handle. For other POSIX platforms
+without proprietary extensions, it is not possible to get a valid file descriptor to the contents
+of a symlink, and in this situation the native handle returned will be `-1` and the preprocessor
+macro `LLFIO_SYMLINK_HANDLE_IS_FAKED` will be non-zero.
+
+If `LLFIO_SYMLINK_HANDLE_IS_FAKED` is on, the handle is race free up to the containing directory
+only. If a third party relocates the symbolic link into a different directory, and race free
+checking is enabled, this class will simply refuse to work with `errc::no_such_file_or_directory`
+as it no longer has any way of finding the symbolic link. You should take care that this does not
+become a denial of service attack.
+
+On Microsoft Windows, there are many kinds of symbolic link: this implementation supports
+directory junctions, and NTFS symbolic links. Reads of any others will return an error
+code comparing equal to `errc::protocol_not_supported`. One should note that modifying symbolic
+links was not historically permitted by users with ordinary permissions on Microsoft Windows,
+however recent versions of Windows 10 do support symbolic links for ordinary users. All versions
+of Windows support directory symbolic links (junctions), these work for all users in any configuration.
+*/
+class LLFIO_DECL symlink_handle : public handle, public fs_handle
+{
+#if LLFIO_SYMLINK_HANDLE_IS_FAKED
+ // Need to retain a handle to our base and our leafname
+ path_handle _dirh;
+ handle::path_type _leafname;
+#endif
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept final { return *this; }
+
+#ifndef _WIN32
+ friend result<void> detail::stat_from_symlink(struct stat &s, const handle &h) noexcept;
+ result<void> _create_symlink(const path_handle &dirh, const handle::path_type &filename, path_view target, deadline d, bool atomic_replace) noexcept;
+#endif
+
+public:
+ using path_type = handle::path_type;
+ using extent_type = handle::extent_type;
+ using size_type = handle::size_type;
+ using mode = handle::mode;
+ using creation = handle::creation;
+ using caching = handle::caching;
+ using flag = handle::flag;
+ using dev_t = fs_handle::dev_t;
+ using ino_t = fs_handle::ino_t;
+ using path_view_type = fs_handle::path_view_type;
+
+ //! The type of symbolic link this is
+ enum class symlink_type
+ {
+ none, //!<! No link
+ symbolic, //!< Standard symbolic link
+
+ win_wsl, //!< WSL symbolic link (Windows only)
+ win_junction //!< NTFS directory junction (Windows only, directories and volumes only)
+ };
+
+ //! The buffer type used by this handle, which is a `path_view`
+ using buffer_type = path_view;
+ /*! The buffers type used by this handle for reads, which is a single item sequence of `path_view`.
+
+ \warning Unless you supply your own kernel buffer, you need to keep this around as long as you
+ use the path view, as the path is a view of the original buffer filled by
+ the kernel and the existence of this keeps that original buffer around.
+ */
+ struct buffers_type
+ {
+ //! Type of the pointer to the buffer.
+ using pointer = path_view *;
+ //! Type of the iterator to the buffer.
+ using iterator = path_view *;
+ //! Type of the iterator to the buffer.
+ using const_iterator = const path_view *;
+ //! Type of the length of the buffers.
+ using size_type = size_t;
+
+ //! Default constructor
+ constexpr buffers_type() {} // NOLINT
+
+ //! Constructor
+ constexpr buffers_type(path_view link, symlink_type type = symlink_type::symbolic)
+ : _link(link)
+ , _type(type)
+ {
+ }
+ ~buffers_type() = default;
+ //! Move constructor
+ buffers_type(buffers_type &&o) noexcept : _link(o._link), _type(o._type), _kernel_buffer(std::move(o._kernel_buffer)), _kernel_buffer_size(o._kernel_buffer_size)
+ {
+ o._link = {};
+ o._type = symlink_type::none;
+ o._kernel_buffer_size = 0;
+ }
+ //! No copy construction
+ buffers_type(const buffers_type &) = delete;
+ //! Move assignment
+ buffers_type &operator=(buffers_type &&o) noexcept
+ {
+ this->~buffers_type();
+ new(this) buffers_type(std::move(o));
+ return *this;
+ }
+ //! No copy assignment
+ buffers_type &operator=(const buffers_type &) = delete;
+
+ //! Returns an iterator to the beginning of the buffers
+ constexpr iterator begin() noexcept { return &_link; }
+ //! Returns an iterator to the beginning of the buffers
+ constexpr const_iterator begin() const noexcept { return &_link; }
+ //! Returns an iterator to the beginning of the buffers
+ constexpr const_iterator cbegin() const noexcept { return &_link; }
+ //! Returns an iterator to after the end of the buffers
+ constexpr iterator end() noexcept { return &_link + 1; }
+ //! Returns an iterator to after the end of the buffers
+ constexpr const_iterator end() const noexcept { return &_link + 1; }
+ //! Returns an iterator to after the end of the buffers
+ constexpr const_iterator cend() const noexcept { return &_link + 1; }
+
+ //! The path referenced by the symbolic link
+ path_view path() const noexcept { return _link; }
+ //! The type of the symbolic link
+ symlink_type type() const noexcept { return _type; }
+
+ private:
+ friend class symlink_handle;
+ path_view _link;
+ symlink_type _type{symlink_type::none};
+ std::unique_ptr<char[]> _kernel_buffer;
+ size_t _kernel_buffer_size{0};
+ };
+ /*! The constant buffers type used by this handle for writes, which is a single item sequence of `path_view`.
+ */
+ struct const_buffers_type
+ {
+ //! Type of the pointer to the buffer.
+ using pointer = const path_view *;
+ //! Type of the iterator to the buffer.
+ using iterator = const path_view *;
+ //! Type of the iterator to the buffer.
+ using const_iterator = const path_view *;
+ //! Type of the length of the buffers.
+ using size_type = size_t;
+
+ //! Constructor
+ constexpr const_buffers_type(path_view link, symlink_type type = symlink_type::symbolic)
+ : _link(link)
+ , _type(type)
+ {
+ }
+ ~const_buffers_type() = default;
+ //! Move constructor
+ const_buffers_type(const_buffers_type &&o) noexcept : _link(o._link), _type(o._type)
+ {
+ o._link = {};
+ o._type = symlink_type::none;
+ }
+ //! No copy construction
+ const_buffers_type(const buffers_type &) = delete;
+ //! Move assignment
+ const_buffers_type &operator=(const_buffers_type &&o) noexcept
+ {
+ this->~const_buffers_type();
+ new(this) const_buffers_type(std::move(o));
+ return *this;
+ }
+ //! No copy assignment
+ const_buffers_type &operator=(const const_buffers_type &) = delete;
+
+ //! Returns an iterator to the beginning of the buffers
+ constexpr iterator begin() noexcept { return &_link; }
+ //! Returns an iterator to the beginning of the buffers
+ constexpr const_iterator begin() const noexcept { return &_link; }
+ //! Returns an iterator to the beginning of the buffers
+ constexpr const_iterator cbegin() const noexcept { return &_link; }
+ //! Returns an iterator to after the end of the buffers
+ constexpr iterator end() noexcept { return &_link + 1; }
+ //! Returns an iterator to after the end of the buffers
+ constexpr const_iterator end() const noexcept { return &_link + 1; }
+ //! Returns an iterator to after the end of the buffers
+ constexpr const_iterator cend() const noexcept { return &_link + 1; }
+
+ //! The path referenced by the symbolic link
+ path_view path() const noexcept { return _link; }
+ //! The type of the symbolic link
+ symlink_type type() const noexcept { return _type; }
+
+ private:
+ friend class symlink_handle;
+ path_view _link;
+ symlink_type _type{symlink_type::none};
+ };
+ //! The i/o request type used by this handle.
+ template <class T, bool = true> struct io_request;
+ //! Specialisation for reading symlinks
+ template <bool ____> struct io_request<buffers_type, ____> // workaround lack of nested specialisation support on older compilers
+ {
+ span<char> kernelbuffer{};
+
+ constexpr io_request() {} // NOLINT
+ //! Construct a request to read a link with optionally specified kernel buffer
+ constexpr io_request(span<char> _kernelbuffer)
+ : kernelbuffer(_kernelbuffer)
+ {
+ }
+ //! Convenience constructor constructing from anything a `span<char>` can construct from
+ LLFIO_TEMPLATE(class... Args)
+ LLFIO_TREQUIRES(LLFIO_TPRED(std::is_constructible<span<char>, Args...>::value))
+ constexpr io_request(Args &&... args) noexcept : io_request(span<char>(static_cast<Args &&>(args)...)) {}
+ };
+ //! Specialisation for writing symlinks
+ template <bool ____> struct io_request<const_buffers_type, ____> // workaround lack of nested specialisation support on older compilers
+ {
+ const_buffers_type buffers;
+ span<char> kernelbuffer;
+ //! Construct a request to write a link with optionally specified kernel buffer
+ io_request(const_buffers_type _buffers, span<char> _kernelbuffer = span<char>())
+ : buffers(std::move(_buffers))
+ , kernelbuffer(_kernelbuffer)
+ {
+ }
+ //! Convenience constructor constructing from anything a `path_view` can construct from
+ LLFIO_TEMPLATE(class... Args)
+ LLFIO_TREQUIRES(LLFIO_TPRED(std::is_constructible<path_view, Args...>::value))
+ constexpr io_request(Args &&... args) noexcept : buffers(path_view(static_cast<Args &&>(args)...)) {}
+ //! Convenience constructor constructing a specific type of link from anything a `path_view` can construct from
+ LLFIO_TEMPLATE(class... Args)
+ LLFIO_TREQUIRES(LLFIO_TPRED(std::is_constructible<path_view, Args...>::value))
+ constexpr io_request(symlink_type type, Args &&... args) noexcept : buffers(path_view(static_cast<Args &&>(args)...), type) {}
+ };
+
+//! Default constructor
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ constexpr
+#endif
+ symlink_handle()
+ {
+ } // NOLINT
+//! Construct a handle from a supplied native handle
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ constexpr
+#endif
+ explicit symlink_handle(native_handle_type h, dev_t devid, ino_t inode, flag flags = flag::none)
+ : handle(std::move(h), caching::all, flags)
+ , fs_handle(devid, inode)
+ {
+ }
+//! Explicit conversion from handle permitted
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+ constexpr
+#endif
+ explicit symlink_handle(handle &&o) noexcept : handle(std::move(o))
+ {
+ }
+ //! Move construction permitted
+ symlink_handle(symlink_handle &&) = default;
+ //! No copy construction (use `clone()`)
+ symlink_handle(const symlink_handle &) = delete;
+ //! Move assignment permitted
+ symlink_handle &operator=(symlink_handle &&o) noexcept
+ {
+ this->~symlink_handle();
+ new(this) symlink_handle(std::move(o));
+ return *this;
+ }
+ //! No copy assignment
+ symlink_handle &operator=(const symlink_handle &) = delete;
+ //! Swap with another instance
+ LLFIO_MAKE_FREE_FUNCTION
+ void swap(symlink_handle &o) noexcept
+ {
+ symlink_handle temp(std::move(*this));
+ *this = std::move(o);
+ o = std::move(temp);
+ }
+
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ~symlink_handle() override
+ {
+ if(_v)
+ {
+ (void) symlink_handle::close();
+ }
+ }
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
+ {
+ LLFIO_LOG_FUNCTION_CALL(this);
+ if(_flags & flag::unlink_on_first_close)
+ {
+ auto ret = unlink();
+ if(!ret)
+ {
+ // File may have already been deleted, if so ignore
+ if(ret.error() != errc::no_such_file_or_directory)
+ {
+ return ret.error();
+ }
+ }
+ }
+#if !LLFIO_SYMLINK_HANDLE_IS_FAKED
+#ifndef NDEBUG
+ if(_v)
+ {
+ // Tell handle::close() that we have correctly executed
+ _v.behaviour |= native_handle_type::disposition::_child_close_executed;
+ }
+#endif
+ return handle::close();
+#else
+ _dirh = {};
+ _leafname = path_type();
+ _v = {};
+ return success();
+#endif
+ }
+
+ /*! Clone this handle (copy constructor is disabled to avoid accidental copying),
+ optionally race free reopening the handle with different access or caching.
+
+ Microsoft Windows provides a syscall for cloning an existing handle but with new
+ access. On POSIX, we must loop calling `current_path()`,
+ trying to open the path returned and making sure it is the same inode.
+
+ \errors Any of the values POSIX dup() or DuplicateHandle() can return.
+ \mallocs On POSIX if changing the mode, we must loop calling `current_path()` and
+ trying to open the path returned. Thus many allocations may occur.
+ */
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<symlink_handle> clone(mode mode_ = mode::unchanged, deadline d = std::chrono::seconds(30)) const noexcept;
+
+#if LLFIO_SYMLINK_HANDLE_IS_FAKED
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<path_type> current_path() const noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ result<void> relink(const path_handle &base, path_view_type path, bool atomic_replace = true, deadline d = std::chrono::seconds(30)) noexcept override;
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC
+ result<void> unlink(deadline d = std::chrono::seconds(30)) noexcept override;
+#endif
+
+ /*! Create a symlink handle opening access to a symbolic link.
+
+ For obvious reasons, one cannot append to a symbolic link, nor create with truncate.
+ In this situation a failure comparing equal to `errc::function_not_supported` shall
+ be returned.
+
+ \errors Any of the values POSIX open() or CreateFile() can return.
+ \mallocs None, unless `LLFIO_SYMLINK_HANDLE_IS_FAKED` is on, in which case one.
+ */
+ LLFIO_MAKE_FREE_FUNCTION
+ static LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<symlink_handle> symlink(const path_handle &base, path_view_type path, mode _mode = mode::read, creation _creation = creation::open_existing, flag flags = flag::none) noexcept;
+ /*! Create a symlink handle creating a randomly named symlink on a path.
+ The symlink is opened exclusively with `creation::only_if_not_exist` so it
+ will never collide with nor overwrite any existing symlink.
+
+ \errors Any of the values POSIX open() or CreateFile() can return,
+ or failure to allocate memory.
+ */
+ LLFIO_MAKE_FREE_FUNCTION
+ static inline result<symlink_handle> random_symlink(const path_handle &dirpath, mode _mode = mode::write, flag flags = flag::none) noexcept
+ {
+ try
+ {
+ for(;;)
+ {
+ auto randomname = utils::random_string(32);
+ randomname.append(".random");
+ result<symlink_handle> ret = symlink(dirpath, randomname, _mode, creation::only_if_not_exist, flags);
+ if(ret || (!ret && ret.error() != errc::file_exists))
+ {
+ return ret;
+ }
+ }
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+ }
+
+ /*! Read the contents of the symbolic link.
+
+ If supplying your own `kernelbuffer`, be aware that the length of the contents of the symbolic
+ link may change at any time. You should therefore retry reading the symbolic link, expanding
+ your `kernelbuffer` each time, until a successful read occurs.
+
+ \return Returns the buffers filled, with its path adjusted to the bytes filled.
+ \param req A buffer to fill with the contents of the symbolic link.
+ \param kernelbuffer A buffer to use for the kernel to fill. If left defaulted, a kernel buffer
+ is allocated internally and stored into `req.buffers` which needs to not be destructed until one
+ is no longer using any items within (the path returned is a view onto the original kernel data).
+ \errors Any of the errors which `readlinkat()` or `DeviceIoControl()` might return, or failure
+ to allocate memory if the user did not supply a kernel buffer to use, or the user supplied buffer
+ was too small.
+ \mallocs If the `kernelbuffer` parameter is set on entry, no memory allocations.
+ If unset, then at least one memory allocation, possibly more is performed.
+ */
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<buffers_type> read(io_request<buffers_type> req = {}) noexcept;
+
+ /*! Write the contents of the symbolic link.
+
+ \param req A buffer with which to replace the contents of the symbolic link.
+ \param d An optional deadline by which the i/o must complete, else it is cancelled. Ignored
+ on Windows.
+ \errors Any of the errors which `symlinkat()` or `DeviceIoControl()` might return.
+ \mallocs On Windows, if the `kernelbuffer` parameter is set on entry, no memory allocations.
+ If unset, then at least one memory allocation, possibly more is performed. On POSIX,
+ at least one memory allocation.
+ */
+ LLFIO_MAKE_FREE_FUNCTION
+ LLFIO_HEADERS_ONLY_VIRTUAL_SPEC result<const_buffers_type> write(io_request<const_buffers_type> req, deadline d = deadline()) noexcept;
+};
+
+//! \brief Constructor for `symlink_handle`
+template <> struct construct<symlink_handle>
+{
+ const path_handle &base;
+ symlink_handle::path_view_type _path;
+ symlink_handle::mode _mode{symlink_handle::mode::read};
+ symlink_handle::creation _creation{symlink_handle::creation::open_existing};
+ result<symlink_handle> operator()() const noexcept { return symlink_handle::symlink(base, _path, _mode, _creation); }
+};
+
+
+LLFIO_V2_NAMESPACE_END
+
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
+#ifdef _WIN32
+#include "detail/impl/windows/symlink_handle.ipp"
+#else
+#include "detail/impl/posix/symlink_handle.ipp"
+#endif
+#undef LLFIO_INCLUDED_BY_HEADER
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/include/afio/v2.0/utils.hpp b/include/llfio/v2.0/utils.hpp
index 5869bf2a..0de1930e 100644
--- a/include/afio/v2.0/utils.hpp
+++ b/include/llfio/v2.0/utils.hpp
@@ -22,11 +22,11 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_UTILS_H
-#define AFIO_UTILS_H
+#ifndef LLFIO_UTILS_H
+#define LLFIO_UTILS_H
-#ifndef AFIO_CONFIG_HPP
-#error You must include the master afio.hpp, not individual header files directly
+#ifndef LLFIO_CONFIG_HPP
+#error You must include the master llfio.hpp, not individual header files directly
#endif
#include "config.hpp"
@@ -34,7 +34,7 @@ Distributed under the Boost Software License, Version 1.0.
//! \file utils.hpp Provides namespace utils
-AFIO_V2_NAMESPACE_EXPORT_BEGIN
+LLFIO_V2_NAMESPACE_EXPORT_BEGIN
namespace utils
{
@@ -44,14 +44,14 @@ namespace utils
\ingroup utils
\complexity{Whatever the system API takes (one would hope constant time).}
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC size_t page_size() noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC size_t page_size() noexcept;
/*! \brief Round a value to its next lowest page size multiple
*/
template <class T> inline T round_down_to_page_size(T i) noexcept
{
const size_t pagesize = page_size();
- i = (T)(AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i) & ~(pagesize - 1)); // NOLINT
+ i = (T)(LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i) & ~(pagesize - 1)); // NOLINT
return i;
}
/*! \brief Round a value to its next highest page size multiple
@@ -59,7 +59,7 @@ namespace utils
template <class T> inline T round_up_to_page_size(T i) noexcept
{
const size_t pagesize = page_size();
- i = (T)((AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i) + pagesize - 1) & ~(pagesize - 1)); // NOLINT
+ i = (T)((LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i) + pagesize - 1) & ~(pagesize - 1)); // NOLINT
return i;
}
/*! \brief Round a pair of a pointer and a size_t to their nearest page size multiples. The pointer will be rounded
@@ -68,8 +68,7 @@ namespace utils
template <class T> inline T round_to_page_size(T i) noexcept
{
const size_t pagesize = page_size();
- i.data = reinterpret_cast<byte *>((AFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i.data)) & ~(pagesize - 1));
- i.len = (i.len + pagesize - 1) & ~(pagesize - 1);
+ i = {reinterpret_cast<byte *>((LLFIO_V2_NAMESPACE::detail::unsigned_integer_cast<uintptr_t>(i.data())) & ~(pagesize - 1)), (i.size() + pagesize - 1) & ~(pagesize - 1)};
return i;
}
@@ -81,7 +80,7 @@ namespace utils
\complexity{Whatever the system API takes (one would hope constant time).}
\exceptionmodel{Any error from the operating system or std::bad_alloc.}
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC std::vector<size_t> page_sizes(bool only_actually_available = true);
+ LLFIO_HEADERS_ONLY_FUNC_SPEC std::vector<size_t> page_sizes(bool only_actually_available = true);
/*! \brief Returns a reasonable default size for page_allocator, typically the closest page size from
page_sizes() to 1Mb.
@@ -121,7 +120,7 @@ namespace utils
\complexity{Whatever the system API takes.}
\exceptionmodel{Any error from the operating system.}
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC void random_fill(char *buffer, size_t bytes) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC void random_fill(char *buffer, size_t bytes) noexcept;
/*! \brief Returns a cryptographically random string capable of being used as a filename. Essentially random_fill() + to_hex_string().
@@ -142,7 +141,7 @@ namespace utils
/*! \brief Tries to flush all modified data to the physical device.
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC result<void> flush_modified_data() noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<void> flush_modified_data() noexcept;
/*! \brief Tries to flush all modified data to the physical device, and then drop the OS filesystem cache,
thus making all future reads come from the physical device. Currently only implemented for Microsoft Windows and Linux.
@@ -151,7 +150,7 @@ namespace utils
For obvious reasons, calling this will have a severe negative impact on performance, but it's very useful for
benchmarking cold cache vs warm cache performance.
*/
- AFIO_HEADERS_ONLY_FUNC_SPEC result<void> drop_filesystem_cache() noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<void> drop_filesystem_cache() noexcept;
namespace detail
{
@@ -180,8 +179,8 @@ namespace utils
ret.actual_size = (bytes + ret.page_size_used - 1) & ~(ret.page_size_used - 1);
return ret;
}
- AFIO_HEADERS_ONLY_FUNC_SPEC large_page_allocation allocate_large_pages(size_t bytes);
- AFIO_HEADERS_ONLY_FUNC_SPEC void deallocate_large_pages(void *p, size_t bytes);
+ LLFIO_HEADERS_ONLY_FUNC_SPEC large_page_allocation allocate_large_pages(size_t bytes);
+ LLFIO_HEADERS_ONLY_FUNC_SPEC void deallocate_large_pages(void *p, size_t bytes);
} // namespace detail
/*! \class page_allocator
\brief An STL allocator which allocates large TLB page memory.
@@ -197,7 +196,7 @@ namespace utils
unmodified.
A particularly useful combination with this allocator is with the
- page_sizes() member function of __afio_dispatcher__. This will return which
+ page_sizes() member function of __llfio_dispatcher__. This will return which
pages sizes are possible, and which page sizes are enabled for this user. If
writing a file copy routine for example, using this allocator with the
largest page size as the copy chunk makes a great deal of sense.
@@ -278,16 +277,16 @@ namespace utils
template <class T, class U> inline bool operator==(const page_allocator<T> & /*unused*/, const page_allocator<U> & /*unused*/) noexcept { return true; }
} // namespace utils
-AFIO_V2_NAMESPACE_END
+LLFIO_V2_NAMESPACE_END
-#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
-#define AFIO_INCLUDED_BY_HEADER 1
+#if LLFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define LLFIO_INCLUDED_BY_HEADER 1
#ifdef _WIN32
#include "detail/impl/windows/utils.ipp"
#else
#include "detail/impl/posix/utils.ipp"
#endif
-#undef AFIO_INCLUDED_BY_HEADER
+#undef LLFIO_INCLUDED_BY_HEADER
#endif
diff --git a/include/llfio/version.hpp b/include/llfio/version.hpp
new file mode 100644
index 00000000..f5421418
--- /dev/null
+++ b/include/llfio/version.hpp
@@ -0,0 +1,34 @@
+//! \file version.hpp Controls the version of LLFIO for cmake, shared library and C++ namespace mangling
+#undef LLFIO_VERSION_MAJOR
+#undef LLFIO_VERSION_MINOR
+#undef LLFIO_VERSION_PATCH
+#undef LLFIO_VERSION_REVISION
+#undef LLFIO_VERSION_GLUE2
+#undef LLFIO_VERSION_GLUE
+#undef LLFIO_HEADERS_VERSION
+#undef LLFIO_NAMESPACE_VERSION
+
+//! \brief Major version for cmake and DLL version stamping \ingroup config
+#define LLFIO_VERSION_MAJOR 2
+//! \brief Minor version for cmake and DLL version stamping \ingroup config
+#define LLFIO_VERSION_MINOR 0
+//! \brief Patch version for cmake and DLL version stamping \ingroup config
+#define LLFIO_VERSION_PATCH 0
+//! \brief Revision version for cmake and DLL version stamping \ingroup config
+#define LLFIO_VERSION_REVISION 0
+
+//! \brief Defined between stable releases of LLFIO. It means the inline namespace
+//! will be permuted per-commit to ensure ABI uniqueness. \ingroup config
+#define LLFIO_UNSTABLE_VERSION
+
+#define LLFIO_VERSION_GLUE2(a, b, c) a##b##c
+#define LLFIO_VERSION_GLUE(a, b, c) LLFIO_VERSION_GLUE2(a, b, c)
+#define LLFIO_NAMESPACE_VERSION LLFIO_VERSION_GLUE(LLFIO_VERSION_MAJOR, _, LLFIO_VERSION_MINOR)
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#define LLFIO_HEADERS_VERSION LLFIO_VERSION_GLUE(LLFIO_VERSION_MAJOR, ., LLFIO_VERSION_MINOR)
+#else
+#define LLFIO_HEADERS_VERSION LLFIO_VERSION_MAJOR.LLFIO_VERSION_MINOR
+#endif
+//! \brief The namespace LLFIO_V2_NAMESPACE::v ## LLFIO_NAMESPACE_VERSION
+#define LLFIO_NAMESPACE_VERSION LLFIO_VERSION_GLUE(LLFIO_VERSION_MAJOR, _, LLFIO_VERSION_MINOR)
diff --git a/meta/libraries.json b/meta/libraries.json
index de7b7a94..5077ef2c 100644
--- a/meta/libraries.json
+++ b/meta/libraries.json
@@ -1,6 +1,6 @@
{
- "key": "afio",
- "name": "AFIO",
+ "key": "LLfio",
+ "name": "LLFIO",
"authors": [ "Niall Douglas", "Paul Kirth" ],
"maintainers": [ "Niall Douglas" ],
"description": "A hard guarantee asynchronous file i/o and filesystem library.",
diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt
index b4020613..556c399c 100644
--- a/programs/CMakeLists.txt
+++ b/programs/CMakeLists.txt
@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
-if(NOT TARGET afio::hl)
- add_subdirectory(.. afio EXCLUDE_FROM_ALL)
+if(NOT TARGET llfio::hl)
+ add_subdirectory(.. llfio EXCLUDE_FROM_ALL)
endif()
-project(afio-programs VERSION 1.0 LANGUAGES CXX)
+project(llfio-programs VERSION 1.0 LANGUAGES CXX)
# Looks like cmake's toolset for LLVM-vs* has some serious problems
if(CMAKE_GENERATOR_TOOLSET MATCHES "LLVM-vs.*")
@@ -37,7 +37,7 @@ function(make_program program)
)
endfunction()
-make_program(benchmark-iostreams afio::hl)
-make_program(benchmark-locking afio::hl)
-make_program(fs-probe afio::hl)
-make_program(key-value-store afio::hl)
+make_program(benchmark-iostreams llfio::hl)
+make_program(benchmark-locking llfio::hl)
+make_program(fs-probe llfio::hl)
+make_program(key-value-store llfio::hl)
diff --git a/programs/benchmark-iostreams/main.cpp b/programs/benchmark-iostreams/main.cpp
index 8c680a14..2592c920 100644
--- a/programs/benchmark-iostreams/main.cpp
+++ b/programs/benchmark-iostreams/main.cpp
@@ -1,4 +1,4 @@
-/* Test the latency of iostreams vs AFIO
+/* Test the latency of iostreams vs LLFIO
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Apr 2018
@@ -26,11 +26,11 @@ Distributed under the Boost Software License, Version 1.0.
#define MAXBLOCKSIZE (4096)
#define REGIONSIZE (100 * 1024 * 1024)
-#include "../../include/afio/afio.hpp"
+#include "../../include/llfio/llfio.hpp"
#if __has_include("quickcpplib/include/algorithm/small_prng.hpp")
#include "quickcpplib/include/algorithm/small_prng.hpp"
#else
-#include "../../include/afio/v2.0/quickcpplib/include/algorithm/small_prng.hpp"
+#include "../../include/llfio/v2.0/quickcpplib/include/algorithm/small_prng.hpp"
#endif
#include <chrono>
@@ -38,7 +38,7 @@ Distributed under the Boost Software License, Version 1.0.
#include <iostream>
#include <vector>
-namespace afio = AFIO_V2_NAMESPACE;
+namespace llfio = LLFIO_V2_NAMESPACE;
using QUICKCPPLIB_NAMESPACE::algorithm::small_prng::small_prng;
inline uint64_t ticksclock()
@@ -148,9 +148,9 @@ template <class F> inline void run_test(const char *csv, off_t max_extent, F &&f
int main()
{
{
- auto th = afio::file({}, "testfile", afio::file_handle::mode::write, afio::file_handle::creation::if_needed).value();
+ auto th = llfio::file({}, "testfile", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed).value();
std::vector<char> buffer(REGIONSIZE, 'a');
- th.write(0, {{(afio::byte *) buffer.data(), buffer.size()}}).value();
+ th.write(0, {{(llfio::byte *) buffer.data(), buffer.size()}}).value();
th.barrier({}, true, true).value();
}
{
@@ -160,8 +160,8 @@ int main()
}
#if 0
{
- std::cout << "Testing latency of afio::file_handle with random malloc/free ..." << std::endl;
- auto th = afio::file({}, "testfile").value();
+ std::cout << "Testing latency of llfio::file_handle with random malloc/free ..." << std::endl;
+ auto th = llfio::file({}, "testfile").value();
std::vector<void *> allocations(1024 * 1024);
small_prng rand;
for(auto &i : allocations)
@@ -169,7 +169,7 @@ int main()
i = malloc(rand() % 4096);
}
run_test("file_handle_malloc_free.csv", 1024 * 1024, [&](unsigned offset, char *buffer, size_t len) {
- th.read(offset, {{(afio::byte *) buffer, len}}).value();
+ th.read(offset, {{(llfio::byte *) buffer, len}}).value();
for(size_t n = 0; n < rand() % 64; n++)
{
size_t i = rand() % (1024 * 1024);
@@ -196,21 +196,21 @@ int main()
}
#endif
{
- std::cout << "Testing latency of afio::file_handle ..." << std::endl;
- auto th = afio::file({}, "testfile").value();
- run_test("file_handle.csv", REGIONSIZE, [&](unsigned offset, char *buffer, size_t len) { th.read(offset, {{(afio::byte *) buffer, len}}).value(); });
+ std::cout << "Testing latency of llfio::file_handle ..." << std::endl;
+ auto th = llfio::file({}, "testfile").value();
+ run_test("file_handle.csv", REGIONSIZE, [&](unsigned offset, char *buffer, size_t len) { th.read(offset, {{(llfio::byte *) buffer, len}}).value(); });
}
#if 1
{
- std::cout << "Testing latency of afio::mapped_file_handle ..." << std::endl;
- auto th = afio::mapped_file({}, "testfile").value();
- run_test("mapped_file_handle.csv", REGIONSIZE, [&](unsigned offset, char *buffer, size_t len) { th.read(offset, {{(afio::byte *) buffer, len}}).value(); });
+ std::cout << "Testing latency of llfio::mapped_file_handle ..." << std::endl;
+ auto th = llfio::mapped_file({}, "testfile").value();
+ run_test("mapped_file_handle.csv", REGIONSIZE, [&](unsigned offset, char *buffer, size_t len) { th.read(offset, {{(llfio::byte *) buffer, len}}).value(); });
}
#endif
#if 1
{
std::cout << "Testing latency of memcpy ..." << std::endl;
- auto th = afio::map(REGIONSIZE).value();
+ auto th = llfio::map(REGIONSIZE).value();
#if 1
{
// Prefault
@@ -226,7 +226,7 @@ int main()
memcpy(buffer, th.address() + offset, len);
#else
// Can't use memcpy, it gets elided
- const afio::byte *__restrict s = th.address() + offset;
+ const llfio::byte *__restrict s = th.address() + offset;
#if defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
while(len >= 4 * sizeof(__m128i))
{
@@ -288,5 +288,5 @@ int main()
});
}
#endif
- afio::filesystem::remove("testfile");
+ llfio::filesystem::remove("testfile");
}
diff --git a/programs/benchmark-locking/main.cpp b/programs/benchmark-locking/main.cpp
index 16d7bbb9..531ce780 100644
--- a/programs/benchmark-locking/main.cpp
+++ b/programs/benchmark-locking/main.cpp
@@ -22,7 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-//! On exit dumps a CSV file of the AFIO log, one per child worker
+//! On exit dumps a CSV file of the LLFIO log, one per child worker
#define DEBUG_CSV 1
//! Seconds to run the benchmark
@@ -30,7 +30,7 @@ Distributed under the Boost Software License, Version 1.0.
#define _CRT_SECURE_NO_WARNINGS 1
-#include "../../include/afio/afio.hpp"
+#include "../../include/llfio/llfio.hpp"
#include "kerneltest/include/kerneltest/v1.0/child_process.hpp"
#include <fstream>
@@ -63,15 +63,15 @@ bool kbhit()
}
#endif
-namespace afio = AFIO_V2_NAMESPACE;
+namespace llfio = LLFIO_V2_NAMESPACE;
namespace child_process = KERNELTEST_V1_NAMESPACE::child_process;
static volatile size_t *shared_memory;
static void initialise_shared_memory()
{
- auto fh = afio::file_handle::file({}, "shared_memory", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::temporary).value();
- auto sh = afio::section_handle::section(fh, 8, afio::section_handle::flag::write).value();
- auto mp = afio::map_handle::map(sh).value();
+ auto fh = llfio::file_handle::file({}, "shared_memory", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::temporary).value();
+ auto sh = llfio::section_handle::section(fh, 8, llfio::section_handle::flag::write).value();
+ auto mp = llfio::map_handle::map(sh).value();
shared_memory = (size_t *) mp.address();
if(!shared_memory)
abort();
@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
std::vector<child_process::child_process> children;
auto mypath = child_process::current_process_path();
#ifdef UNICODE
- std::vector<afio::filesystem::path::string_type> args = {L"spawned", L"", L"", L"", L"00"};
+ std::vector<llfio::filesystem::path::string_type> args = {L"spawned", L"", L"", L"", L"00"};
args[1].resize(strlen(argv[1]));
for(size_t n = 0; n < args[1].size(); n++)
args[1][n] = argv[1][n];
@@ -132,7 +132,7 @@ int main(int argc, char *argv[])
for(size_t n = 0; n < args[3].size(); n++)
args[3][n] = argv[3][n];
#else
- std::vector<afio::filesystem::path::string_type> args = {"spawned", argv[1], argv[2], argv[3], "00"};
+ std::vector<llfio::filesystem::path::string_type> args = {"spawned", argv[1], argv[2], argv[3], "00"};
#endif
auto env = child_process::current_process_env();
std::cout << "Launching " << waiters << " copies of myself as a child process ..." << std::endl;
@@ -282,59 +282,59 @@ int main(int argc, char *argv[])
// Wait for parent to let me proceed
std::atomic<int> done(-1);
std::thread worker([test, contended, total_locks, this_child, &done, &count] {
- std::unique_ptr<afio::algorithm::shared_fs_mutex::shared_fs_mutex> algorithm;
- auto base = afio::path_handle::path(".").value();
+ std::unique_ptr<llfio::algorithm::shared_fs_mutex::shared_fs_mutex> algorithm;
+ auto base = llfio::path_handle::path(".").value();
switch(test)
{
case lock_algorithm::atomic_append:
{
- auto v = afio::algorithm::shared_fs_mutex::atomic_append::fs_mutex_append({}, "lockfile");
+ auto v = llfio::algorithm::shared_fs_mutex::atomic_append::fs_mutex_append({}, "lockfile");
if(v.has_error())
{
std::cerr << "ERROR: Creation of lock algorithm returns " << v.error().message() << std::endl;
return;
}
- algorithm = std::make_unique<afio::algorithm::shared_fs_mutex::atomic_append>(std::move(v.value()));
+ algorithm = std::make_unique<llfio::algorithm::shared_fs_mutex::atomic_append>(std::move(v.value()));
break;
}
case lock_algorithm::byte_ranges:
{
- auto v = afio::algorithm::shared_fs_mutex::byte_ranges::fs_mutex_byte_ranges({}, "lockfile");
+ auto v = llfio::algorithm::shared_fs_mutex::byte_ranges::fs_mutex_byte_ranges({}, "lockfile");
if(v.has_error())
{
std::cerr << "ERROR: Creation of lock algorithm returns " << v.error().message() << std::endl;
return;
}
- algorithm = std::make_unique<afio::algorithm::shared_fs_mutex::byte_ranges>(std::move(v.value()));
+ algorithm = std::make_unique<llfio::algorithm::shared_fs_mutex::byte_ranges>(std::move(v.value()));
break;
}
case lock_algorithm::lock_files:
{
- auto v = afio::algorithm::shared_fs_mutex::lock_files::fs_mutex_lock_files(base);
+ auto v = llfio::algorithm::shared_fs_mutex::lock_files::fs_mutex_lock_files(base);
if(v.has_error())
{
std::cerr << "ERROR: Creation of lock algorithm returns " << v.error().message() << std::endl;
return;
}
- algorithm = std::make_unique<afio::algorithm::shared_fs_mutex::lock_files>(std::move(v.value()));
+ algorithm = std::make_unique<llfio::algorithm::shared_fs_mutex::lock_files>(std::move(v.value()));
break;
}
case lock_algorithm::memory_map:
{
- auto v = afio::algorithm::shared_fs_mutex::memory_map<QUICKCPPLIB_NAMESPACE::algorithm::hash::passthru_hash>::fs_mutex_map({}, "lockfile");
+ auto v = llfio::algorithm::shared_fs_mutex::memory_map<QUICKCPPLIB_NAMESPACE::algorithm::hash::passthru_hash>::fs_mutex_map({}, "lockfile");
if(v.has_error())
{
std::cerr << "ERROR: Creation of lock algorithm returns " << v.error().message() << std::endl;
return;
}
- algorithm = std::make_unique<afio::algorithm::shared_fs_mutex::memory_map<QUICKCPPLIB_NAMESPACE::algorithm::hash::passthru_hash>>(std::move(v.value()));
+ algorithm = std::make_unique<llfio::algorithm::shared_fs_mutex::memory_map<QUICKCPPLIB_NAMESPACE::algorithm::hash::passthru_hash>>(std::move(v.value()));
break;
}
case lock_algorithm::unknown:
break;
}
// Create entities named 0 to total_locks
- std::vector<afio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type> entities(total_locks);
+ std::vector<llfio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type> entities(total_locks);
for(size_t n = 0; n < total_locks; n++)
{
if(contended)
@@ -352,7 +352,7 @@ int main(int argc, char *argv[])
std::this_thread::yield();
while(!done)
{
- auto result = algorithm->lock(entities, afio::deadline(), false);
+ auto result = algorithm->lock(entities, llfio::deadline(), false);
if(result.has_error())
{
std::cerr << "ERROR: Algorithm lock returns " << result.error().message() << std::endl;
@@ -379,10 +379,10 @@ int main(int argc, char *argv[])
std::cout << "\ncount=" << count << " (+" << (count - lastcount) << "), average=" << (count / secs) << std::endl;
lastcount = count;
#if 1
- auto it = afio::log().cbegin();
+ auto it = llfio::log().cbegin();
for(size_t n = 0; n < 10; n++)
{
- if(it == afio::log().cend())
+ if(it == llfio::log().cend())
break;
std::cout << " " << *it;
++it;
@@ -412,8 +412,8 @@ int main(int argc, char *argv[])
worker.join();
std::cout << "RESULTS(" << count << ")" << std::endl;
#if DEBUG_CSV
- std::ofstream s("benchmark_locking_afio_log" + std::to_string(this_child) + ".csv");
- s << csv(afio::log());
+ std::ofstream s("benchmark_locking_llfio_log" + std::to_string(this_child) + ".csv");
+ s << csv(llfio::log());
#endif
return 0;
}
diff --git a/programs/fs-probe/main.cpp b/programs/fs-probe/main.cpp
index 94121c57..2ef117ae 100644
--- a/programs/fs-probe/main.cpp
+++ b/programs/fs-probe/main.cpp
@@ -24,20 +24,20 @@ Distributed under the Boost Software License, Version 1.0.
#define _CRT_SECURE_NO_WARNINGS 1
-#include "../../include/afio/afio.hpp"
+#include "../../include/llfio/llfio.hpp"
#include <fstream>
#include <iomanip>
#include <iostream>
#ifdef __linux__
-#define file_handle AFIO_V2_NAMESPACE::file_handle
+#define file_handle LLFIO_V2_NAMESPACE::file_handle
#endif
constexpr unsigned permute_flags_max = 4;
static const std::regex sp_preamble{"(system|storage).*"};
-static AFIO_V2_NAMESPACE::storage_profile::storage_profile profile[permute_flags_max];
+static LLFIO_V2_NAMESPACE::storage_profile::storage_profile profile[permute_flags_max];
#define RETCHECK(expr) \
{ \
@@ -51,8 +51,8 @@ static AFIO_V2_NAMESPACE::storage_profile::storage_profile profile[permute_flags
int main(int argc, char *argv[])
{
- using namespace AFIO_V2_NAMESPACE;
- using AFIO_V2_NAMESPACE::byte;
+ using namespace LLFIO_V2_NAMESPACE;
+ using LLFIO_V2_NAMESPACE::byte;
std::regex torun(".*");
bool regexvalid = false;
unsigned torunflags = (1 << permute_flags_max) - 1;
diff --git a/programs/key-value-store/Readme.md b/programs/key-value-store/Readme.md
index 2299f7cb..2b3fd5a4 100644
--- a/programs/key-value-store/Readme.md
+++ b/programs/key-value-store/Readme.md
@@ -1,13 +1,13 @@
Herein lies an exploratory toy ACID key-value store written using
-AFIO which lets you look up any BLOB value from some 128-bit key, and to
+LLFIO which lets you look up any BLOB value from some 128-bit key, and to
update as an atomic transaction up to 65,535 key-values at once.
It is purely to test the feasibility of one approach to implementing such
-a store, and to test AFIO's design. Nobody should use this store for
+a store, and to test LLFIO's design. Nobody should use this store for
anything serious.
## Todo:
-- [x] Add sparse file creation on Windows to AFIO and see how the
+- [x] Add sparse file creation on Windows to LLFIO and see how the
benchmarks fare.
- [x] Add key-value deletion.
- [x] Atomic append should issue gather buffers of `IOV_MAX`
diff --git a/programs/key-value-store/include/key_value_store.hpp b/programs/key-value-store/include/key_value_store.hpp
index 9ef3af06..9dd45d22 100644
--- a/programs/key-value-store/include/key_value_store.hpp
+++ b/programs/key-value-store/include/key_value_store.hpp
@@ -25,21 +25,21 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef KEY_VALUE_STORE_HPP
#define KEY_VALUE_STORE_HPP
-#include "../../../include/afio/afio.hpp"
+#include "../../../include/llfio/llfio.hpp"
#if __has_include("quickcpplib/include/algorithm/open_hash_index.hpp")
#include "quickcpplib/include/algorithm/open_hash_index.hpp"
#else
-#include "../../../include/afio/v2.0/quickcpplib/include/algorithm/open_hash_index.hpp"
+#include "../../../include/llfio/v2.0/quickcpplib/include/algorithm/open_hash_index.hpp"
#endif
#include <vector>
namespace key_value_store
{
- namespace afio = AFIO_V2_NAMESPACE;
- template <class T> using optional = afio::optional<T>;
- template <class T> using span = afio::span<T>;
- using afio::undoer;
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ template <class T> using optional = llfio::optional<T>;
+ template <class T> using span = llfio::span<T>;
+ using llfio::undoer;
using uint128 = QUICKCPPLIB_NAMESPACE::integers128::uint128;
using key_type = uint128;
@@ -127,7 +127,7 @@ namespace key_value_store
- uint128 key 16 bytes
- value_history 104 bytes
*/
- using open_hash_index = basic_open_hash_index<atomic_linear_memory_policy<key_type, value_history, 0>, AFIO_V2_NAMESPACE::algorithm::mapped_span>;
+ using open_hash_index = basic_open_hash_index<atomic_linear_memory_policy<key_type, value_history, 0>, LLFIO_V2_NAMESPACE::mapped>;
static_assert(sizeof(open_hash_index::value_type) == 128, "open_hash_index::value_type is wrong size");
struct index
@@ -159,21 +159,21 @@ namespace key_value_store
class basic_key_value_store
{
friend class transaction;
- afio::file_handle _indexfile;
- afio::file_handle _mysmallfile; // append only
- afio::file_handle::extent_guard _indexfileguard, _smallfileguard;
+ llfio::file_handle _indexfile;
+ llfio::file_handle _mysmallfile; // append only
+ llfio::file_handle::extent_guard _indexfileguard, _smallfileguard;
size_t _mysmallfileidx{(size_t) -1};
struct
{
- std::vector<afio::file_handle> blocking;
- std::vector<afio::mapped_file_handle> mapped;
+ std::vector<llfio::file_handle> blocking;
+ std::vector<llfio::mapped_file_handle> mapped;
} _smallfiles;
optional<index::open_hash_index> _index;
index::index *_indexheader{nullptr};
std::mutex _commitlock;
size_t _mmap_over_extension{0};
- static constexpr afio::file_handle::extent_type _indexinuseoffset = INT64_MAX;
+ static constexpr llfio::file_handle::extent_type _indexinuseoffset = INT64_MAX;
static constexpr uint64_t _goodmagic = 0x3130564b4f494641; // "AFIOKV01"
static constexpr uint64_t _badmagic = 0x3130564b44414544; // "DEADKV01"
@@ -182,11 +182,11 @@ namespace key_value_store
// We append a value_tail record and round up to 64 byte multiple
return (length + sizeof(index::value_tail) + 63) & ~63;
}
- void _openfiles(const afio::path_handle &dir, afio::file_handle::mode mode, afio::file_handle::caching caching)
+ void _openfiles(const llfio::path_handle &dir, llfio::file_handle::mode mode, llfio::file_handle::caching caching)
{
- const afio::file_handle::mode smallfilemode =
+ const llfio::file_handle::mode smallfilemode =
#ifdef _WIN32
- afio::file_handle::mode::read
+ llfio::file_handle::mode::read
#else
// Linux won't allow taking an exclusive lock on a read only file
mode
@@ -200,18 +200,18 @@ namespace key_value_store
for(size_t n = 0; n < 48; n++)
{
name = std::to_string(n);
- auto fh = afio::file_handle::file(dir, name, smallfilemode, afio::file_handle::creation::open_existing, afio::file_handle::caching::all, afio::file_handle::flag::disable_prefetching);
+ auto fh = llfio::file_handle::file(dir, name, smallfilemode, llfio::file_handle::creation::open_existing, llfio::file_handle::caching::all, llfio::file_handle::flag::disable_prefetching);
if(fh)
{
retry:
bool claimed = false;
- if(mode == afio::file_handle::mode::write && !_mysmallfile.is_valid())
+ if(mode == llfio::file_handle::mode::write && !_mysmallfile.is_valid())
{
// Try to claim this small file
auto smallfileclaimed = fh.value().try_lock(_indexinuseoffset, 1, true);
if(smallfileclaimed)
{
- _mysmallfile = afio::file_handle::file(dir, name, afio::file_handle::mode::write, afio::file_handle::creation::open_existing, caching).value();
+ _mysmallfile = llfio::file_handle::file(dir, name, llfio::file_handle::mode::write, llfio::file_handle::creation::open_existing, caching).value();
_mysmallfile.set_append_only(true).value();
_smallfileguard = std::move(smallfileclaimed).value();
_mysmallfileidx = n;
@@ -224,16 +224,16 @@ namespace key_value_store
{
#ifndef _WIN32
// We really need this to only have read only perms, otherwise any mmaps will extend the file ludicrously
- fh = afio::file_handle::file(dir, name, afio::file_handle::mode::read, afio::file_handle::creation::open_existing, afio::file_handle::caching::all, afio::file_handle::flag::disable_prefetching);
+ fh = llfio::file_handle::file(dir, name, llfio::file_handle::mode::read, llfio::file_handle::creation::open_existing, llfio::file_handle::caching::all, llfio::file_handle::flag::disable_prefetching);
#endif
_smallfiles.blocking.push_back(std::move(fh).value());
}
continue;
}
- else if(mode == afio::file_handle::mode::write && !_mysmallfile.is_valid())
+ else if(mode == llfio::file_handle::mode::write && !_mysmallfile.is_valid())
{
// Going to need a new smallfile
- fh = afio::file_handle::file(dir, name, afio::file_handle::mode::write, afio::file_handle::creation::only_if_not_exist, caching);
+ fh = llfio::file_handle::file(dir, name, llfio::file_handle::mode::write, llfio::file_handle::creation::only_if_not_exist, caching);
if(fh)
{
fh.value().truncate(64).value();
@@ -243,14 +243,14 @@ namespace key_value_store
}
break;
}
- if(mode == afio::file_handle::mode::write && !_mysmallfile.is_valid())
+ if(mode == llfio::file_handle::mode::write && !_mysmallfile.is_valid())
{
throw maximum_writers_reached();
}
// Set up the index, either r/w or read only with copy on write
- afio::section_handle::flag mapflags = (mode == afio::file_handle::mode::write) ? afio::section_handle::flag::readwrite : (afio::section_handle::flag::read | afio::section_handle::flag::cow);
- afio::section_handle sh = afio::section_handle::section(_indexfile, 0, mapflags).value();
- afio::file_handle::extent_type len = sh.length().value();
+ llfio::section_handle::flag mapflags = (mode == llfio::file_handle::mode::write) ? llfio::section_handle::flag::readwrite : (llfio::section_handle::flag::read | llfio::section_handle::flag::cow);
+ llfio::section_handle sh = llfio::section_handle::section(_indexfile, 0, mapflags).value();
+ llfio::file_handle::extent_type len = sh.length().value();
len -= sizeof(index::index);
len /= sizeof(index::open_hash_index::value_type);
size_t offset = sizeof(index::index);
@@ -270,10 +270,10 @@ namespace key_value_store
basic_key_value_store &operator=(const basic_key_value_store &) = delete;
basic_key_value_store &operator=(basic_key_value_store &&) = delete;
- basic_key_value_store(const afio::path_handle &dir, size_t hashtableentries, bool enable_integrity = false, afio::file_handle::mode mode = afio::file_handle::mode::write, afio::file_handle::caching caching = afio::file_handle::caching::all)
- : _indexfile(afio::file_handle::file(dir, "index", mode, (mode == afio::file_handle::mode::write) ? afio::file_handle::creation::if_needed : afio::file_handle::creation::open_existing, caching, afio::file_handle::flag::disable_prefetching).value())
+ basic_key_value_store(const llfio::path_handle &dir, size_t hashtableentries, bool enable_integrity = false, llfio::file_handle::mode mode = llfio::file_handle::mode::write, llfio::file_handle::caching caching = llfio::file_handle::caching::all)
+ : _indexfile(llfio::file_handle::file(dir, "index", mode, (mode == llfio::file_handle::mode::write) ? llfio::file_handle::creation::if_needed : llfio::file_handle::creation::open_existing, caching, llfio::file_handle::flag::disable_prefetching).value())
{
- if(mode == afio::file_handle::mode::write)
+ if(mode == llfio::file_handle::mode::write)
{
// Try an exclusive lock on inuse byte of the index file
auto indexinuse = _indexfile.try_lock(_indexinuseoffset, 1, true);
@@ -282,15 +282,15 @@ namespace key_value_store
// I am the first entrant into this data store
if(_indexfile.maximum_extent().value() == 0)
{
- afio::file_handle::extent_type size = sizeof(index::index) + (hashtableentries) * sizeof(index::open_hash_index::value_type);
- size = afio::utils::round_up_to_page_size(size);
+ llfio::file_handle::extent_type size = sizeof(index::index) + (hashtableentries) * sizeof(index::open_hash_index::value_type);
+ size = llfio::utils::round_up_to_page_size(size);
_indexfile.truncate(size).value();
index::index i;
memset(&i, 0, sizeof(i));
i.magic = _goodmagic;
i.all_writes_synced = _indexfile.are_writes_durable();
i.contents_hashed = enable_integrity;
- _indexfile.write(0, {{(afio::byte *) &i, sizeof(i)}}).value();
+ _indexfile.write(0, {{(llfio::byte *) &i, sizeof(i)}}).value();
}
else
{
@@ -306,18 +306,18 @@ namespace key_value_store
}
// Now we've finished the checks, reset writes_occurring and all_writes_synced
index::index i;
- _indexfile.read(0, {{(afio::byte *) &i, sizeof(i)}}).value();
+ _indexfile.read(0, {{(llfio::byte *) &i, sizeof(i)}}).value();
memset(i.writes_occurring, 0, sizeof(i.writes_occurring));
i.all_writes_synced = _indexfile.are_writes_durable();
memset(&i.hash, 0, sizeof(i.hash));
- _indexfile.write(0, {{(afio::byte *) &i, sizeof(i)}}).value();
+ _indexfile.write(0, {{(llfio::byte *) &i, sizeof(i)}}).value();
}
}
}
// Take a shared lock, blocking if someone is still setting things up
_indexfileguard = _indexfile.lock(_indexinuseoffset, 1, false).value();
{
- afio::byte buffer[8];
+ llfio::byte buffer[8];
_indexfile.read(0, {{buffer, 8}}).value();
auto goodmagic = _goodmagic;
auto badmagic = _badmagic;
@@ -334,13 +334,13 @@ namespace key_value_store
}
}
//! \overload
- basic_key_value_store(const afio::path_view &dir, size_t hashtableentries, bool enable_integrity = false, afio::file_handle::mode mode = afio::file_handle::mode::write, afio::file_handle::caching caching = afio::file_handle::caching::all)
- : basic_key_value_store(afio::directory_handle::directory({}, dir, afio::directory_handle::mode::write, afio::directory_handle::creation::if_needed).value(), hashtableentries, enable_integrity, mode, caching)
+ basic_key_value_store(const llfio::path_view &dir, size_t hashtableentries, bool enable_integrity = false, llfio::file_handle::mode mode = llfio::file_handle::mode::write, llfio::file_handle::caching caching = llfio::file_handle::caching::all)
+ : basic_key_value_store(llfio::directory_handle::directory({}, dir, llfio::directory_handle::mode::write, llfio::directory_handle::creation::if_needed).value(), hashtableentries, enable_integrity, mode, caching)
{
}
//! Opens the store for read only access
- basic_key_value_store(const afio::path_view &dir)
- : basic_key_value_store(afio::path_handle::path(dir).value(), 0, false, afio::file_handle::mode::read)
+ basic_key_value_store(const llfio::path_view &dir)
+ : basic_key_value_store(llfio::path_handle::path(dir).value(), 0, false, llfio::file_handle::mode::read)
{
}
~basic_key_value_store()
@@ -376,7 +376,7 @@ namespace key_value_store
for(size_t n = 0; n < _smallfiles.blocking.size(); n++)
{
auto currentlength = _smallfiles.blocking[n].maximum_extent().value();
- _smallfiles.mapped.push_back(afio::mapped_file_handle(std::move(_smallfiles.blocking[n]), currentlength + overextension));
+ _smallfiles.mapped.push_back(llfio::mapped_file_handle(std::move(_smallfiles.blocking[n]), currentlength + overextension));
}
_smallfileguard.set_handle(&_smallfiles.mapped[_mysmallfileidx]);
_smallfiles.blocking.clear();
@@ -478,7 +478,7 @@ namespace key_value_store
// TODO: Open newly created smallfiles
abort();
}
- afio::byte *buffer;
+ llfio::byte *buffer;
bool free_on_destruct = _smallfiles.mapped.empty();
if(!free_on_destruct)
{
@@ -497,7 +497,7 @@ namespace key_value_store
}
else
{
- buffer = (afio::byte *) malloc(smallfilelength);
+ buffer = (llfio::byte *) malloc(smallfilelength);
if(!buffer)
{
throw std::bad_alloc();
@@ -545,9 +545,9 @@ namespace key_value_store
basic_key_value_store *_parent;
struct _item
{
- basic_key_value_store::keyvalue_info kvi; // the item's value when fetched
- afio::optional<span<const char>> towrite; // the value to be written on commit
- bool remove; // true if to remove
+ basic_key_value_store::keyvalue_info kvi; // the item's value when fetched
+ llfio::optional<span<const char>> towrite; // the value to be written on commit
+ bool remove; // true if to remove
_item(basic_key_value_store::keyvalue_info &&_kvi)
: kvi(std::move(_kvi))
, remove(false)
@@ -739,7 +739,7 @@ namespace key_value_store
bool items_written = false;
if(!_parent->_smallfiles.mapped.empty())
{
- afio::file_handle::extent_type original_length = _parent->_mysmallfile.maximum_extent().value();
+ llfio::file_handle::extent_type original_length = _parent->_mysmallfile.maximum_extent().value();
// How big does this map need to be?
size_t totalcommitsize = 0;
for(size_t n = 0; n < _items.size(); n++)
@@ -751,14 +751,14 @@ namespace key_value_store
if(totalcommitsize >= 4096)
{
auto &mfh = _parent->_smallfiles.mapped[_parent->_mysmallfileidx];
- afio::file_handle::extent_type new_length = original_length + totalcommitsize;
+ llfio::file_handle::extent_type new_length = original_length + totalcommitsize;
if(new_length > mfh.capacity())
{
mfh.reserve(new_length + _parent->_mmap_over_extension).value();
}
mfh.truncate(new_length).value();
- afio::byte *value = mfh.address() + original_length;
- afio::file_handle::extent_type value_offset = original_length;
+ llfio::byte *value = mfh.address() + original_length;
+ llfio::file_handle::extent_type value_offset = original_length;
for(size_t n = 0; n < _items.size(); n++)
{
toupdate_type &thisupdate = toupdate[n];
@@ -803,17 +803,17 @@ namespace key_value_store
if(!items_written)
{
// Gather append write all my items to my smallfile
- afio::file_handle::extent_type value_offset = _parent->_mysmallfile.maximum_extent().value();
+ llfio::file_handle::extent_type value_offset = _parent->_mysmallfile.maximum_extent().value();
assert((value_offset % 64) == 0);
// POSIX guarantees that at least 16 gather buffers can be written in a single shot
- std::vector<afio::file_handle::const_buffer_type> reqs;
+ std::vector<llfio::file_handle::const_buffer_type> reqs;
reqs.reserve(16);
// With tails, that's eight items per syscall
- afio::byte tailbuffers[8][128];
+ llfio::byte tailbuffers[8][128];
memset(tailbuffers, 0, sizeof(tailbuffers));
for(size_t n = 0; n < _items.size(); n++)
{
- afio::byte *tailbuffer = tailbuffers[n % 8];
+ llfio::byte *tailbuffer = tailbuffers[n % 8];
index::value_tail *vt = reinterpret_cast<index::value_tail *>(tailbuffer + 128 - sizeof(index::value_tail));
toupdate_type &thisupdate = toupdate[n];
const transaction::_item &item = _items[n];
@@ -829,7 +829,7 @@ namespace key_value_store
{
QUICKCPPLIB_NAMESPACE::algorithm::hash::fast_hash hasher;
memset(&vt->hash, 0, sizeof(vt->hash));
- hasher.add((const char *) reqs.back().data, reqs.back().len);
+ hasher.add((const char *) reqs.back().data(), reqs.back().size());
vt->hash = hasher.finalise();
}
memset(&thisupdate.history_item, 0, sizeof(thisupdate.history_item));
@@ -840,7 +840,7 @@ namespace key_value_store
totalwrite = _parent->_pad_length(item.towrite->size());
size_t tailbytes = totalwrite - item.towrite->size();
assert(tailbytes < 128);
- reqs.push_back({(afio::byte *) item.towrite->data(), item.towrite->size()});
+ reqs.push_back({(llfio::byte *) item.towrite->data(), item.towrite->size()});
reqs.push_back({tailbuffer + 128 - tailbytes, tailbytes});
if(_parent->_indexheader->contents_hashed)
{
@@ -848,9 +848,9 @@ namespace key_value_store
memset(&vt->hash, 0, sizeof(vt->hash));
auto rit = reqs.end();
rit -= 2;
- hasher.add((char *) rit->data, rit->len);
+ hasher.add((char *) rit->data(), rit->size());
++rit;
- hasher.add((char *) rit->data, rit->len);
+ hasher.add((char *) rit->data(), rit->size());
vt->hash = hasher.finalise();
}
index::value_history::item &history_item = thisupdate.history_item;
diff --git a/programs/key-value-store/main.cpp b/programs/key-value-store/main.cpp
index 96a4eb17..c7d921a6 100644
--- a/programs/key-value-store/main.cpp
+++ b/programs/key-value-store/main.cpp
@@ -26,17 +26,17 @@ Distributed under the Boost Software License, Version 1.0.
namespace stackoverflow
{
- namespace filesystem = AFIO_V2_NAMESPACE::filesystem;
- using string_view = AFIO_V2_NAMESPACE::string_view;
- template <class T> using optional = AFIO_V2_NAMESPACE::optional<T>;
+ namespace filesystem = LLFIO_V2_NAMESPACE::filesystem;
+ using string_view = LLFIO_V2_NAMESPACE::string_view;
+ template <class T> using optional = LLFIO_V2_NAMESPACE::optional<T>;
// Try to read first line from file at path, returning no string if file does not exist,
// throwing exception for any other error
optional<std::string> read_first_line(filesystem::path path)
{
- using namespace AFIO_V2_NAMESPACE;
- using AFIO_V2_NAMESPACE::file_handle;
- using AFIO_V2_NAMESPACE::byte;
+ using namespace LLFIO_V2_NAMESPACE;
+ using LLFIO_V2_NAMESPACE::file_handle;
+ using LLFIO_V2_NAMESPACE::byte;
// The result<T> is from WG21 P0762, it looks quite like an `expected<T, std::error_code>` object
// See Outcome v2 at https://ned14.github.io/outcome/ and https://lists.boost.org/boost-announce/2017/06/0510.php
@@ -75,11 +75,11 @@ namespace stackoverflow
}
// Same as before, either throw any error or unpack the value returned
file_handle::buffers_type buffers_read(_buffers_read.value());
- // Note that buffers returned by AFIO read() may be completely different to buffers submitted
+ // Note that buffers returned by LLFIO read() may be completely different to buffers submitted
// This lets us skip unnecessary memory copying
// Make a string view of the first buffer returned
- string_view v((const char *) buffers_read[0].data, buffers_read[0].len);
+ string_view v((const char *) buffers_read[0].data(), buffers_read[0].size());
// Sub view that view with the first line
string_view line(v.substr(0, v.find_first_of('\n')));
// Return a string copying the first line from the file, or all 4096 bytes read if no newline found.
@@ -97,7 +97,7 @@ void benchmark(key_value_store::basic_key_value_store &store, const char *desc)
std::cout << " Generating 1M key-value pairs ..." << std::endl;
for(size_t n = 0; n < 1000000; n++)
{
- std::string randomvalue = AFIO_V2_NAMESPACE::utils::random_string(1024 / 2);
+ std::string randomvalue = LLFIO_V2_NAMESPACE::utils::random_string(1024 / 2);
values.push_back({100 + n, randomvalue});
}
}
@@ -150,7 +150,7 @@ int main()
{
{
std::error_code ec;
- AFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
+ LLFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
}
{
key_value_store::basic_key_value_store store("teststore", 10);
@@ -224,7 +224,7 @@ int main()
}
{
std::error_code ec;
- AFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
+ LLFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
}
{
key_value_store::basic_key_value_store store("teststore", 2000000);
@@ -232,7 +232,7 @@ int main()
}
{
std::error_code ec;
- AFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
+ LLFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
}
{
key_value_store::basic_key_value_store store("teststore", 2000000, true);
@@ -240,7 +240,7 @@ int main()
}
{
std::error_code ec;
- AFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
+ LLFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
}
{
key_value_store::basic_key_value_store store("teststore", 2000000);
@@ -249,7 +249,7 @@ int main()
}
{
std::error_code ec;
- AFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
+ LLFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
}
{
key_value_store::basic_key_value_store store("teststore", 2000000, true);
@@ -258,10 +258,10 @@ int main()
}
{
std::error_code ec;
- AFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
+ LLFIO_V2_NAMESPACE::filesystem::remove_all("teststore", ec);
}
{
- key_value_store::basic_key_value_store store("teststore", 2000000, true, AFIO_V2_NAMESPACE::file_handle::mode::write, AFIO_V2_NAMESPACE::file_handle::caching::reads);
+ key_value_store::basic_key_value_store store("teststore", 2000000, true, LLFIO_V2_NAMESPACE::file_handle::mode::write, LLFIO_V2_NAMESPACE::file_handle::caching::reads);
store.use_mmaps();
benchmark(store, "integrity, durability, mmaps");
}
diff --git a/release_notes.md b/release_notes.md
index 697fb680..0e1b136b 100644
--- a/release_notes.md
+++ b/release_notes.md
@@ -1,13 +1,13 @@
<center><table border="0" cellpadding="4">
<tr>
-<td align="center"> <a href="https://github.com/ned14/afio">AFIO</a><br><a href="https://github.com/ned14/afio">on GitHub</a> </td>
+<td align="center"> <a href="https://github.com/ned14/llfio">LLFIO</a><br><a href="https://github.com/ned14/llfio">on GitHub</a> </td>
<td align="center"> <a href="http://my.cdash.org/index.php?project=Boost.AFIO">CTest summary</a><br><a href="http://my.cdash.org/index.php?project=Boost.AFIO">dashboard</a> </td>
-<td align="center"> <a href="https://travis-ci.org/ned14/afio">Linux and MacOS CI:</a><img src="https://travis-ci.org/ned14/afio.svg?branch=master"/> </td>
-<td align="center"> <a href="https://ci.appveyor.com/project/ned14/afio/branch/master">Windows CI:</a><img src="https://ci.appveyor.com/api/projects/status/680b1pt9srnoprs3/branch/master?svg=true"/> </td>
-<td align="center"> <a href="https://dedi5.nedprod.com/static/files/afio-v2.0-source-latest.tar.xz">Latest stable</a><br><a href="https://dedi5.nedprod.com/static/files/afio-v2.0-source-latest.tar.xz">sources</a> </td>
-<td align="center"> <a href="https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-linux64-latest.tgz">Latest stable</a><br><a href="https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-linux64-latest.tgz">Linux x64 prebuilt</a> </td>
-<td align="center"> <!--<a href="https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-darwin-latest.tgz">Latest stable</a><br><a href="https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-darwin64-latest.tgz">OS X x64 prebuilt</a>--> </td>
-<td align="center"> <a href="https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-win64-latest.zip">Latest stable</a><br/><a href="https://dedi5.nedprod.com/static/files/afio-v2.0-binaries-win64-latest.zip">VS2017 x64 prebuilt</a> </td>
+<td align="center"> <a href="https://travis-ci.org/ned14/llfio">Linux and MacOS CI:</a><img src="https://travis-ci.org/ned14/llfio.svg?branch=master"/> </td>
+<td align="center"> <a href="https://ci.appveyor.com/project/ned14/llfio/branch/master">Windows CI:</a><img src="https://ci.appveyor.com/api/projects/status/dfctqfap3kpx89om/branch/master?svg=true"/> </td>
+<td align="center"> <a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-source-latest.tar.xz">Latest stable</a><br><a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-source-latest.tar.xz">sources</a> </td>
+<td align="center"> <a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-linux64-latest.tgz">Latest stable</a><br><a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-linux64-latest.tgz">Linux x64 prebuilt</a> </td>
+<td align="center"> <!--<a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-darwin-latest.tgz">Latest stable</a><br><a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-darwin64-latest.tgz">OS X x64 prebuilt</a>--> </td>
+<td align="center"> <a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-win64-latest.zip">Latest stable</a><br/><a href="https://dedi5.nedprod.com/static/files/llfio-v2.0-binaries-win64-latest.zip">VS2017 x64 prebuilt</a> </td>
</tr>
</table></center>
@@ -21,7 +21,7 @@ filesystem algorithms which work well with directly mapped non-volatile storage
as Intel Optane.
It is a complete rewrite after a Boost peer review in August 2015. Its github
-source code repository lives at https://github.com/ned14/boost.afio.
+source code repository lives at https://github.com/ned14/boost.llfio.
- Portable to any conforming C++ 14 compiler with a working Filesystem TS in its STL.
- Will make use of any Concepts TS if you have them.
@@ -55,10 +55,10 @@ These compilers and OS are regularly tested:
- Visual Studio 2017 (Windows 10 x64)
Other compilers, architectures and OSs may work, but are not tested regularly. You will need a Filesystem TS
-implementation in your STL and C++ 14. See https://github.com/ned14/afio/blob/master/programs/fs-probe/fs_probe_results.yaml
+implementation in your STL and C++ 14. See https://github.com/ned14/llfio/blob/master/programs/fs-probe/fs_probe_results.yaml
for a database of latencies for various previously tested OS, filing systems and storage devices.
-Todo list for already implemented parts: https://ned14.github.io/afio/todo.html
+Todo list for already implemented parts: https://ned14.github.io/llfio/todo.html
To build and test (make, ninja etc):
@@ -67,7 +67,7 @@ mkdir build
cd build
cmake ..
cmake --build .
-ctest -R afio_sl
+ctest -R llfio_sl
~~~
To build and test (Visual Studio, XCode etc):
@@ -77,7 +77,7 @@ mkdir build
cd build
cmake ..
cmake --build . --config Release
-ctest -C Release -R afio_sl
+ctest -C Release -R llfio_sl
~~~
## v2 architecture and design implemented:
@@ -87,12 +87,12 @@ ctest -C Release -R afio_sl
| ✔ | ✔ | Universal native handle/fd abstraction instead of `void *`.
| ✔ | ✔ | Perfectly/Ideally low memory (de)allocation per op (usually none).
| ✔ | ✔ | noexcept API throughout returning error_code for failure instead of throwing exceptions.
-| ✔ | ✔ | AFIO v1 handle type split into hierarchy of types:<ol><li>handle - provides open, close, get path, clone, set/unset append only, change caching, characteristics<li>fs_handle - handles with an inode number<li>path_handle - a race free anchor to a subset of the filesystem<li>directory_handle - enumerates the filesystem<li>io_handle - adds synchronous scatter-gather i/o, byte range locking<li>file_handle - adds open/create file, get and set maximum extent<li>async_file_handle - adds asynchronous scatter-gather i/o<li>mapped_file_handle - adds low latency memory mapped scatter-gather i/o</ol>
+| ✔ | ✔ | LLFIO v1 handle type split into hierarchy of types:<ol><li>handle - provides open, close, get path, clone, set/unset append only, change caching, characteristics<li>fs_handle - handles with an inode number<li>path_handle - a race free anchor to a subset of the filesystem<li>directory_handle - enumerates the filesystem<li>io_handle - adds synchronous scatter-gather i/o, byte range locking<li>file_handle - adds open/create file, get and set maximum extent<li>async_file_handle - adds asynchronous scatter-gather i/o<li>mapped_file_handle - adds low latency memory mapped scatter-gather i/o</ol>
| ✔ | ✔ | Cancelable i/o (made possible thanks to dropping XP support).
| ✔ | ✔ | All shared_ptr usage removed as all use of multiple threads removed.
| ✔ | ✔ | Use of std::vector to transport scatter-gather sequences replaced with C++ 20 `span<>` borrowed views.
| ✔ | ✔ | Completion callbacks are now some arbitrary type `U&&` instead of a future continuation. Type erasure for its storage is bound into the one single memory allocation for everything needed to execute the op, and so therefore overhead is optimal.
-| ✔ | ✔ | Filing system algorithms made generic and broken out into public `afio::algorithms` template library (the AFIO FTL).
+| ✔ | ✔ | Filing system algorithms made generic and broken out into public `llfio::algorithms` template library (the LLFIO FTL).
| ✔ | ✔ | Abstraction of native handle management via bitfield specified "characteristics".
| ✔ | | Storage profiles, a YAML database of behaviours of hardware, OS and filing system combinations.
| ✔ | | Absolute and interval deadline timed i/o throughout (made possible thanks to dropping XP support).
@@ -131,8 +131,8 @@ Todo:
| ✔ | ✔ | ✔ | i/o deadlines and cancellation.
| | ✔ | ✔ | Retrieving and setting the current maximum extent (size) of an open file.
| | ✔ | ✔ | Retrieving the current path of an open file irrespective of where it has been renamed to by third parties.
-| | ✔ | ✔ | statfs_t ported over from AFIO v1.
-| | ✔ | ✔ | utils namespace ported over from AFIO v1.
+| | ✔ | ✔ | statfs_t ported over from LLFIO v1.
+| | ✔ | ✔ | utils namespace ported over from LLFIO v1.
| ✔ | ✔ | ✔ | `shared_fs_mutex` shared/exclusive entities locking based on lock files
| ✔ | ✔ | ✔ | Byte range shared/exclusive locking.
| ✔ | ✔ | ✔ | `shared_fs_mutex` shared/exclusive entities locking based on byte ranges
@@ -140,24 +140,19 @@ Todo:
| | ✔ | ✔ | Memory mapped files and virtual memory management (`section_handle`, `map_handle` and `mapped_file_handle`)
| ✔ | ✔ | ✔ | `shared_fs_mutex` shared/exclusive entities locking based on memory maps
| ✔ | ✔ | ✔ | Universal portable UTF-8 path views.
-| | ✔ | ✔ | "Hole punching" and hole enumeration ported over from AFIO v1.
-| | ✔ | ✔ | Directory handles and very fast directory enumeration ported over from AFIO v1.
+| | ✔ | ✔ | "Hole punching" and hole enumeration ported over from LLFIO v1.
+| | ✔ | ✔ | Directory handles and very fast directory enumeration ported over from LLFIO v1.
| ✔ | ✔ | ✔ | `shared_fs_mutex` shared/exclusive entities locking based on safe byte ranges
| | ✔ | ✔ | Set random or sequential i/o (prefetch).
| ✔ | ✔ | ✔ | i/o on `async_file_handle` is coroutines awaitable.
-| ✔ | ✔ | | `afio::algorithm::trivial_vector<T>` with constant time reallocation if `T` is trivially copyable.
-
-Todo to reach feature parity with AFIO v1:
-
-| NEW in v2 | Windows | POSIX | |
-| --------- | --------| ----- | --- |
-| | | | `symlink_handle`.
-| | | | BSD and OS X kqueues optimised `io_service`
+| ✔ | ✔ | | `llfio::algorithm::trivial_vector<T>` with constant time reallocation if `T` is trivially copyable.
+| | ✔ | ✔ | `symlink_handle`.
Todo thereafter in order of priority:
| NEW in v2 | Windows | POSIX | |
| --------- | --------| ----- | --- |
+| ✔ | | | A mechanism for writing a `stat_t` onto an inode.
| ✔ | | | Page allocator based on an index of linked list of free pages. See notes.
| ✔ | | | Optionally concurrent B+ tree index based on page allocator for key-value store.
| ✔ | | | Attributes extending `span<buffers_type>` with DMA colouring.
@@ -179,7 +174,7 @@ Features possibly to be added after a Boost peer review:
<table width="100%" border="0" cellpadding="4">
<tr>
-<th colspan="3">Why you might need AFIO<hr></th>
+<th colspan="3">Why you might need LLFIO<hr></th>
</tr>
<tr>
<td valign="top" width="33%">
@@ -193,13 +188,13 @@ Manufacturer claimed 4Kb transfer latencies for the physical hardware:
- RTT PCIe latency: **0.5us**
</td>
<td valign="top" width="33%">
-100% read QD1 4Kb direct transfer latencies for the software with AFIO:
+100% read QD1 4Kb direct transfer latencies for the software with LLFIO:
- &lt; 99% spinning rust hard drive latency: Windows **187,231us** FreeBSD **9,836us** Linux **26,468us**
- &lt; 99% SATA flash drive latency: Windows **290us** Linux **158us**
- &lt; 99% NVMe drive latency: Windows **37us** FreeBSD **70us** Linux **30us**
</td>
<td valign="top" width="33%">
-75% read 25% write QD4 4Kb direct transfer latencies for the software with AFIO:
+75% read 25% write QD4 4Kb direct transfer latencies for the software with LLFIO:
- &lt; 99% spinning rust hard drive latency: Windows **48,185us** FreeBSD **61,834us** Linux **104,507us**
- &lt; 99% SATA flash drive latency: Windows **1,812us** Linux **1,416us**
- &lt; 99% NVMe drive latency: Windows **50us** FreeBSD **143us** Linux **40us**
diff --git a/scripts/make_free_functions.py b/scripts/make_free_functions.py
index 6b2d6f1f..0368b261 100644
--- a/scripts/make_free_functions.py
+++ b/scripts/make_free_functions.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Look for all static member functions marked AFIO_MAKE_FREE_FUNCTION and make them free
+# Look for all static member functions marked LLFIO_MAKE_FREE_FUNCTION and make them free
# (C) 2017 Niall Douglas
from __future__ import print_function
@@ -15,11 +15,11 @@ for header in glob.glob("../include/afio/*/*.hpp"):
for lineidx in range(0, len(lines)):
if lines[lineidx].startswith('class'):
current_class = lines[lineidx][6:lines[lineidx].find(':')]
- current_class = current_class.replace('AFIO_DECL', '').lstrip().rstrip()
- if 'AFIO_MAKE_FREE_FUNCTION' in lines[lineidx] and re.match('\s*AFIO_MAKE_FREE_FUNCTION', lines[lineidx]):
+ current_class = current_class.replace('LLFIO_DECL', '').lstrip().rstrip()
+ if 'LLFIO_MAKE_FREE_FUNCTION' in lines[lineidx] and re.match('\s*LLFIO_MAKE_FREE_FUNCTION', lines[lineidx]):
function = ''
for n in range(1, 100):
- if 'AFIO_REQUIRES' in lines[lineidx+n]:
+ if 'LLFIO_REQUIRES' in lines[lineidx+n]:
continue
function += lines[lineidx+n]
if lineidx+n+1 >= len(lines):
@@ -47,9 +47,9 @@ for header in glob.glob("../include/afio/*/*.hpp"):
if functions_to_be_freed_begin != -1:
del lines[functions_to_be_freed_begin+1:functions_to_be_freed_end]
else:
- # Place just before the last AFIO_V2_NAMESPACE_END
+ # Place just before the last LLFIO_V2_NAMESPACE_END
functions_to_be_freed_begin = len(lines)-1
- while not lines[functions_to_be_freed_begin].startswith('AFIO_V2_NAMESPACE_END'):
+ while not lines[functions_to_be_freed_begin].startswith('LLFIO_V2_NAMESPACE_END'):
functions_to_be_freed_begin = functions_to_be_freed_begin - 1
lines.insert(functions_to_be_freed_begin, '// END make_free_functions.py\n\n')
lines.insert(functions_to_be_freed_begin, '// BEGIN make_free_functions.py\n')
@@ -58,8 +58,8 @@ for header in glob.glob("../include/afio/*/*.hpp"):
print((classname, function))
function = function.replace('virtual ', '')
function = function.replace('override', '')
- function = function.replace('AFIO_HEADERS_ONLY_MEMFUNC_SPEC ', '')
- function = function.replace('AFIO_HEADERS_ONLY_VIRTUAL_SPEC ', '')
+ function = function.replace('LLFIO_HEADERS_ONLY_MEMFUNC_SPEC ', '')
+ function = function.replace('LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ', '')
completion_template = 'template <class CompletionRoutine>' in function
function = function.replace('template <class CompletionRoutine> ', '')
is_static = 'static ' in function
diff --git a/src/afio.cpp b/src/afio.cpp
deleted file mode 100644
index c8674b44..00000000
--- a/src/afio.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#define AFIO_DYN_LINK 1
-#define AFIO_SOURCE 1
-#include "../include/afio/afio.hpp"
diff --git a/src/llfio.cpp b/src/llfio.cpp
new file mode 100644
index 00000000..4174d6d9
--- /dev/null
+++ b/src/llfio.cpp
@@ -0,0 +1,3 @@
+#define LLFIO_DYN_LINK 1
+#define LLFIO_SOURCE 1
+#include "../include/llfio/llfio.hpp"
diff --git a/test/kerneltest b/test/kerneltest
-Subproject 07491646b1c1f875d22512e0630902c142eeae5
+Subproject 3172681c82a503b395749a2458f462346480240
diff --git a/test/test_kernel_decl.hpp b/test/test_kernel_decl.hpp
index b1ec993c..afac7aa0 100644
--- a/test/test_kernel_decl.hpp
+++ b/test/test_kernel_decl.hpp
@@ -22,36 +22,37 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#ifndef AFIO_TEST_KERNEL_DECL_HPP
-#define AFIO_TEST_KERNEL_DECL_HPP
+#ifndef LLFIO_TEST_KERNEL_DECL_HPP
+#define LLFIO_TEST_KERNEL_DECL_HPP
#ifdef BOOST_KERNELTEST_PLEASE_INLINE_TEST_KERNELS
// We have been included as part of an inline test suite
-#define AFIO_TEST_KERNEL_DECL inline
+#define LLFIO_TEST_KERNEL_DECL inline
#else
// We are standalone
-#include "../include/afio/afio.hpp"
-#define AFIO_TEST_KERNEL_DECL extern inline QUICKCPPLIB_SYMBOL_EXPORT
+#include "../include/llfio/llfio.hpp"
+#define LLFIO_TEST_KERNEL_DECL extern inline QUICKCPPLIB_SYMBOL_EXPORT
#endif
-#if AFIO_EXPERIMENTAL_STATUS_CODE
+#if LLFIO_EXPERIMENTAL_STATUS_CODE
#define KERNELTEST_EXPERIMENTAL_STATUS_CODE 1
+#include "outcome/include/outcome/experimental/status-code/include/iostream_support.hpp"
#endif
#include "kerneltest/include/kerneltest.hpp"
#if 0
-// Tell KernelTest's outcome how to grok AFIO's result
+// Tell KernelTest's outcome how to grok LLFIO's result
OUTCOME_V2_NAMESPACE_BEGIN
namespace convert
{
- // Provide custom ValueOrError conversion from afio::result<U> into kerneltest::result<T>
- template <class T, class U> struct value_or_error<KERNELTEST_V1_NAMESPACE::result<T>, AFIO_V2_NAMESPACE::result<U>>
+ // Provide custom ValueOrError conversion from llfio::result<U> into kerneltest::result<T>
+ template <class T, class U> struct value_or_error<KERNELTEST_V1_NAMESPACE::result<T>, LLFIO_V2_NAMESPACE::result<U>>
{
static constexpr bool enable_result_inputs = true;
static constexpr bool enable_outcome_inputs = true;
template <class X, //
- typename = std::enable_if_t<std::is_same<AFIO_V2_NAMESPACE::result<U>, std::decay_t<X>>::value //
+ typename = std::enable_if_t<std::is_same<LLFIO_V2_NAMESPACE::result<U>, std::decay_t<X>>::value //
&& std::is_constructible<T, U>::value>> //
constexpr KERNELTEST_V1_NAMESPACE::result<T>
operator()(X &&src)
@@ -63,14 +64,14 @@ namespace convert
KERNELTEST_V1_NAMESPACE::result<T>{make_error_code(std::forward<X>(src).error())};
}
};
- // Provide custom ValueOrError conversion from afio::result<U> into kerneltest::outcome<T>
- template <class T, class U> struct value_or_error<KERNELTEST_V1_NAMESPACE::outcome<T>, AFIO_V2_NAMESPACE::result<U>>
+ // Provide custom ValueOrError conversion from llfio::result<U> into kerneltest::outcome<T>
+ template <class T, class U> struct value_or_error<KERNELTEST_V1_NAMESPACE::outcome<T>, LLFIO_V2_NAMESPACE::result<U>>
{
static constexpr bool enable_result_inputs = true;
static constexpr bool enable_outcome_inputs = true;
template <class X, //
- typename = std::enable_if_t<std::is_same<AFIO_V2_NAMESPACE::result<U>, std::decay_t<X>>::value //
+ typename = std::enable_if_t<std::is_same<LLFIO_V2_NAMESPACE::result<U>, std::decay_t<X>>::value //
&& std::is_constructible<T, U>::value>> //
constexpr KERNELTEST_V1_NAMESPACE::outcome<T>
operator()(X &&src)
@@ -84,8 +85,8 @@ namespace convert
};
}
OUTCOME_V2_NAMESPACE_END
-static_assert(std::is_constructible<KERNELTEST_V1_NAMESPACE::result<int>, AFIO_V2_NAMESPACE::result<int>>::value, "kerneltest::result<int> is not constructible from afio::result<int>!");
-static_assert(std::is_constructible<KERNELTEST_V1_NAMESPACE::outcome<int>, AFIO_V2_NAMESPACE::result<int>>::value, "kerneltest::outcome<int> is not constructible from afio::result<int>!");
+static_assert(std::is_constructible<KERNELTEST_V1_NAMESPACE::result<int>, LLFIO_V2_NAMESPACE::result<int>>::value, "kerneltest::result<int> is not constructible from llfio::result<int>!");
+static_assert(std::is_constructible<KERNELTEST_V1_NAMESPACE::outcome<int>, LLFIO_V2_NAMESPACE::result<int>>::value, "kerneltest::outcome<int> is not constructible from llfio::result<int>!");
#endif
#endif // namespace
diff --git a/test/tests/async_io.cpp b/test/tests/async_io.cpp
index 14ded93a..1dc07ffb 100644
--- a/test/tests/async_io.cpp
+++ b/test/tests/async_io.cpp
@@ -28,24 +28,24 @@ Distributed under the Boost Software License, Version 1.0.
static inline void TestAsyncFileHandle()
{
- namespace afio = AFIO_V2_NAMESPACE;
- afio::io_service service;
- afio::async_file_handle h = afio::async_file_handle::async_file(service, {}, "temp", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::only_metadata, afio::file_handle::flag::unlink_on_first_close).value();
- std::vector<std::pair<std::future<afio::async_file_handle::const_buffers_type>, afio::async_file_handle::io_state_ptr>> futures;
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ llfio::io_service service;
+ llfio::async_file_handle h = llfio::async_file_handle::async_file(service, {}, "temp", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::only_metadata, llfio::file_handle::flag::unlink_on_first_close).value();
+ std::vector<std::pair<std::future<llfio::async_file_handle::const_buffers_type>, llfio::async_file_handle::io_state_ptr>> futures;
futures.reserve(1024);
h.truncate(1024 * 4096).value();
- alignas(4096) afio::byte buffer[4096];
- memset(buffer, 78, 4096); // NOLINT
- afio::async_file_handle::const_buffer_type bt{buffer, sizeof(buffer)}; // NOLINT
+ alignas(4096) llfio::byte buffer[4096];
+ memset(buffer, 78, 4096); // NOLINT
+ llfio::async_file_handle::const_buffer_type bt{buffer, sizeof(buffer)}; // NOLINT
for(size_t n = 0; n < 1024; n++)
{
retry:
- std::promise<afio::async_file_handle::const_buffers_type> p;
+ std::promise<llfio::async_file_handle::const_buffers_type> p;
auto f(p.get_future());
auto schedule_io = [&] {
- return h.async_write({bt, n * 4096}, [ p = std::move(p), n ](afio::async_file_handle *, afio::async_file_handle::io_result<afio::async_file_handle::const_buffers_type> & result) mutable {
+ return h.async_write({bt, n * 4096}, [ p = std::move(p), n ](llfio::async_file_handle *, llfio::async_file_handle::io_result<llfio::async_file_handle::const_buffers_type> & result) mutable {
(void) n;
- if(!result && result.error() == afio::errc::resource_unavailable_try_again)
+ if(!result && result.error() == llfio::errc::resource_unavailable_try_again)
{
std::cout << "*** Completion handler saw error " << result.error() << std::endl;
}
@@ -62,7 +62,7 @@ static inline void TestAsyncFileHandle()
});
};
auto g(schedule_io());
- if(!g && g.error() == afio::errc::resource_unavailable_try_again)
+ if(!g && g.error() == llfio::errc::resource_unavailable_try_again)
{
// Sleep until at least i/o is processed
service.run().value();
@@ -78,10 +78,10 @@ static inline void TestAsyncFileHandle()
// Make sure nothing went wrong by fetching the futures.
for(auto &i : futures)
{
- afio::async_file_handle::const_buffers_type out = i.first.get();
+ llfio::async_file_handle::const_buffers_type out = i.first.get();
// std::cout << out.data()->len << std::endl;
- BOOST_CHECK(out.data()->len == 4096);
+ BOOST_CHECK(out.data()->size() == 4096);
}
}
-KERNELTEST_TEST_KERNEL(integration, afio, works, async_file_handle, "Tests that afio::async_file_handle works as expected", TestAsyncFileHandle())
+KERNELTEST_TEST_KERNEL(integration, llfio, works, async_file_handle, "Tests that llfio::async_file_handle works as expected", TestAsyncFileHandle())
diff --git a/test/tests/coroutines.cpp b/test/tests/coroutines.cpp
index 24ef46ef..e6a09b6a 100644
--- a/test/tests/coroutines.cpp
+++ b/test/tests/coroutines.cpp
@@ -30,22 +30,22 @@ static inline void TestAsyncFileHandleCoroutines()
{
#ifdef __cpp_coroutines
//! [coroutines_example]
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// Create an i/o service for this thread
- afio::io_service service;
+ llfio::io_service service;
// Create an async file i/o handle attached to the i/o service for this thread
- afio::async_file_handle h = afio::async_file_handle::async_file(service, {}, "temp", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::only_metadata, afio::file_handle::flag::unlink_on_first_close).value();
+ llfio::async_file_handle h = llfio::async_file_handle::async_file(service, {}, "temp", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::only_metadata, llfio::file_handle::flag::unlink_on_first_close).value();
// Truncate to 1Mb
h.truncate(1024 * 4096);
// Launch 8 coroutines, each writing 4Kb of chars 0-8 to every 32Kb block
auto coroutine = [&h](size_t no) -> std::future<void> {
- std::vector<afio::byte, afio::utils::page_allocator<afio::byte>> buffer(4096);
+ std::vector<llfio::byte, llfio::utils::page_allocator<llfio::byte>> buffer(4096);
memset(buffer.data(), (int) ('0' + no), 4096);
- afio::async_file_handle::const_buffer_type bt{buffer.data(), buffer.size()};
+ llfio::async_file_handle::const_buffer_type bt{buffer.data(), buffer.size()};
for(size_t n = 0; n < 128; n++)
{
// This will initiate the i/o, and suspend the coroutine until completion.
@@ -71,8 +71,8 @@ static inline void TestAsyncFileHandleCoroutines()
//! [coroutines_example]
// Check that the file has the right contents
- alignas(4096) afio::byte buffer1[4096], buffer2[4096];
- afio::async_file_handle::extent_type offset = 0;
+ alignas(4096) llfio::byte buffer1[4096], buffer2[4096];
+ llfio::async_file_handle::extent_type offset = 0;
for(size_t n = 0; n < 128; n++)
{
for(size_t m = 0; m < 8; m++)
@@ -89,8 +89,8 @@ static inline void TestAsyncFileHandleCoroutines()
static inline void TestPostSelfToRunCoroutines()
{
#ifdef __cpp_coroutines
- namespace afio = AFIO_V2_NAMESPACE;
- afio::io_service service;
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ llfio::io_service service;
std::atomic<bool> ready(false);
auto runthreadid = QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id();
auto coroutinethread = [&]() -> void {
@@ -98,7 +98,7 @@ static inline void TestPostSelfToRunCoroutines()
auto thisthreadid = QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id();
BOOST_CHECK(thisthreadid != runthreadid);
ready = true;
- co_await afio::io_service::awaitable_post_to_self(service);
+ co_await llfio::io_service::awaitable_post_to_self(service);
thisthreadid = QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id();
BOOST_CHECK(thisthreadid == runthreadid);
// std::cout << "Coroutine exiting" << std::endl;
@@ -121,5 +121,5 @@ static inline void TestPostSelfToRunCoroutines()
#endif
}
-KERNELTEST_TEST_KERNEL(integration, afio, coroutines, async_file_handle, "Tests that afio::async_file_handle works as expected with Coroutines", TestAsyncFileHandleCoroutines())
-KERNELTEST_TEST_KERNEL(integration, afio, coroutines, co_post_self_to_run, "Tests that afio::io_service::co_post_self_to_run() works as expected with Coroutines", TestPostSelfToRunCoroutines())
+KERNELTEST_TEST_KERNEL(integration, llfio, coroutines, async_file_handle, "Tests that llfio::async_file_handle works as expected with Coroutines", TestAsyncFileHandleCoroutines())
+KERNELTEST_TEST_KERNEL(integration, llfio, coroutines, co_post_self_to_run, "Tests that llfio::io_service::co_post_self_to_run() works as expected with Coroutines", TestPostSelfToRunCoroutines())
diff --git a/test/tests/current_path.cpp b/test/tests/current_path.cpp
index 23346a8c..40776008 100644
--- a/test/tests/current_path.cpp
+++ b/test/tests/current_path.cpp
@@ -26,21 +26,21 @@ Distributed under the Boost Software License, Version 1.0.
template <class FileHandleType, class DirectoryHandleType> static inline void TestHandleCurrentPath()
{
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
{
std::error_code ec;
- afio::filesystem::remove_all("tempfile", ec);
- afio::filesystem::remove_all("tempfile2", ec);
- afio::filesystem::remove_all("tempdir", ec);
- afio::filesystem::remove_all("tempdir2", ec);
+ llfio::filesystem::remove_all("tempfile", ec);
+ llfio::filesystem::remove_all("tempfile2", ec);
+ llfio::filesystem::remove_all("tempdir", ec);
+ llfio::filesystem::remove_all("tempdir2", ec);
}
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-braces"
#endif
- afio::path_handle null_path_handle;
- FileHandleType h1 = afio::construct<FileHandleType>{null_path_handle, "tempfile", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::temporary, afio::file_handle::flag::none}().value(); // NOLINT
- DirectoryHandleType h2 = afio::construct<DirectoryHandleType>{null_path_handle, "tempdir", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::all, afio::file_handle::flag::none}().value(); // NOLINT
+ llfio::path_handle null_path_handle;
+ FileHandleType h1 = llfio::construct<FileHandleType>{null_path_handle, "tempfile", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::temporary, llfio::file_handle::flag::none}().value(); // NOLINT
+ DirectoryHandleType h2 = llfio::construct<DirectoryHandleType>{null_path_handle, "tempdir", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::all, llfio::file_handle::flag::none}().value(); // NOLINT
#ifdef __clang__
#pragma clang diagnostic pop
#endif
@@ -156,6 +156,6 @@ template <class FileHandleType, class DirectoryHandleType> static inline void Te
h2.unlink().value();
}
-KERNELTEST_TEST_KERNEL(integration, afio, current_path, handle, "Tests that afio::handle::current_path() works as expected", TestHandleCurrentPath<AFIO_V2_NAMESPACE::file_handle, AFIO_V2_NAMESPACE::directory_handle>())
-KERNELTEST_TEST_KERNEL(integration, afio, current_path, cached_parent_handle_adapter, "Tests that afio::cached_parent_handle_adapter::current_path() works as expected",
- TestHandleCurrentPath<AFIO_V2_NAMESPACE::algorithm::cached_parent_handle_adapter<AFIO_V2_NAMESPACE::file_handle>, AFIO_V2_NAMESPACE::algorithm::cached_parent_handle_adapter<AFIO_V2_NAMESPACE::directory_handle>>())
+KERNELTEST_TEST_KERNEL(integration, llfio, current_path, handle, "Tests that llfio::handle::current_path() works as expected", TestHandleCurrentPath<LLFIO_V2_NAMESPACE::file_handle, LLFIO_V2_NAMESPACE::directory_handle>())
+KERNELTEST_TEST_KERNEL(integration, llfio, current_path, cached_parent_handle_adapter, "Tests that llfio::cached_parent_handle_adapter::current_path() works as expected",
+ TestHandleCurrentPath<LLFIO_V2_NAMESPACE::algorithm::cached_parent_handle_adapter<LLFIO_V2_NAMESPACE::file_handle>, LLFIO_V2_NAMESPACE::algorithm::cached_parent_handle_adapter<LLFIO_V2_NAMESPACE::directory_handle>>())
diff --git a/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp b/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp
index 9cb5eaa9..46d66536 100644
--- a/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp
+++ b/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp
@@ -26,29 +26,29 @@ Distributed under the Boost Software License, Version 1.0.
namespace directory_handle_create_close
{
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle> test_kernel_directory_handle_absolute(AFIO_V2_NAMESPACE::directory_handle::mode m, AFIO_V2_NAMESPACE::directory_handle::creation c, AFIO_V2_NAMESPACE::directory_handle::flag f,
- AFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle> test_kernel_directory_handle_absolute(LLFIO_V2_NAMESPACE::directory_handle::mode m, LLFIO_V2_NAMESPACE::directory_handle::creation c, LLFIO_V2_NAMESPACE::directory_handle::flag f,
+ LLFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
{
- auto h = AFIO_V2_NAMESPACE::directory_handle::directory({}, "testdir", m, c, AFIO_V2_NAMESPACE::directory_handle::caching::all, f);
+ auto h = LLFIO_V2_NAMESPACE::directory_handle::directory({}, "testdir", m, c, LLFIO_V2_NAMESPACE::directory_handle::caching::all, f);
if(h)
{
// git needs a file in a directory to create it, so any directory created needs an empty file called pin.txt
- (void) AFIO_V2_NAMESPACE::file_handle::file(h.value(), "pin.txt", AFIO_V2_NAMESPACE::file_handle::mode::write, AFIO_V2_NAMESPACE::file_handle::creation::if_needed);
- *info = AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
+ (void) LLFIO_V2_NAMESPACE::file_handle::file(h.value(), "pin.txt", LLFIO_V2_NAMESPACE::file_handle::mode::write, LLFIO_V2_NAMESPACE::file_handle::creation::if_needed);
+ *info = LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
h.value().close().value();
}
return h;
}
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle> test_kernel_directory_handle_relative(AFIO_V2_NAMESPACE::directory_handle::mode m, AFIO_V2_NAMESPACE::directory_handle::creation c, AFIO_V2_NAMESPACE::directory_handle::flag f,
- AFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle> test_kernel_directory_handle_relative(LLFIO_V2_NAMESPACE::directory_handle::mode m, LLFIO_V2_NAMESPACE::directory_handle::creation c, LLFIO_V2_NAMESPACE::directory_handle::flag f,
+ LLFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
{
- OUTCOME_TRY(b, AFIO_V2_NAMESPACE::path_handle::path("."));
- auto h = AFIO_V2_NAMESPACE::directory_handle::directory(b, "testdir", m, c, AFIO_V2_NAMESPACE::directory_handle::caching::all, f);
+ OUTCOME_TRY(b, LLFIO_V2_NAMESPACE::path_handle::path("."));
+ auto h = LLFIO_V2_NAMESPACE::directory_handle::directory(b, "testdir", m, c, LLFIO_V2_NAMESPACE::directory_handle::caching::all, f);
if(h)
{
// git needs a file in a directory to create it, so any directory created needs an empty file called pin.txt
- (void) AFIO_V2_NAMESPACE::file_handle::file(h.value(), "pin.txt", AFIO_V2_NAMESPACE::file_handle::mode::write, AFIO_V2_NAMESPACE::file_handle::creation::if_needed);
- *info = AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
+ (void) LLFIO_V2_NAMESPACE::file_handle::file(h.value(), "pin.txt", LLFIO_V2_NAMESPACE::file_handle::mode::write, LLFIO_V2_NAMESPACE::file_handle::creation::if_needed);
+ *info = LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
h.value().close().value();
}
b.close().value();
diff --git a/test/tests/directory_handle_create_close/runner.cpp b/test/tests/directory_handle_create_close/runner.cpp
index 90b1fa1d..0001df01 100644
--- a/test/tests/directory_handle_create_close/runner.cpp
+++ b/test/tests/directory_handle_create_close/runner.cpp
@@ -27,12 +27,12 @@ Distributed under the Boost Software License, Version 1.0.
template <class U> inline void directory_handle_create_close_creation(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
- using AFIO_V2_NAMESPACE::result;
- using directory_handle = AFIO_V2_NAMESPACE::directory_handle;
- static const result<void> no_such_file_or_directory = AFIO_V2_NAMESPACE::errc::no_such_file_or_directory;
- static const result<void> file_exists = AFIO_V2_NAMESPACE::errc::file_exists;
- static const result<void> is_a_directory = AFIO_V2_NAMESPACE::errc::is_a_directory;
- static const result<void> permission_denied = AFIO_V2_NAMESPACE::errc::permission_denied;
+ using LLFIO_V2_NAMESPACE::result;
+ using directory_handle = LLFIO_V2_NAMESPACE::directory_handle;
+ static const result<void> no_such_file_or_directory = LLFIO_V2_NAMESPACE::errc::no_such_file_or_directory;
+ static const result<void> file_exists = LLFIO_V2_NAMESPACE::errc::file_exists;
+ static const result<void> is_a_directory = LLFIO_V2_NAMESPACE::errc::is_a_directory;
+ static const result<void> permission_denied = LLFIO_V2_NAMESPACE::errc::permission_denied;
// clang-format off
static typename directory_handle::buffer_type _entries[5];
@@ -154,5 +154,5 @@ template <class U> inline void directory_handle_create_close_creation(U &&f)
check_results_with_boost_test(permuter, results);
}
-KERNELTEST_TEST_KERNEL(unit, afio, directory_handle_create_close, directory_handle, "Tests that afio::directory_handle::directory()'s parameters with absolute paths work as expected", directory_handle_create_close_creation(directory_handle_create_close::test_kernel_directory_handle_absolute))
-KERNELTEST_TEST_KERNEL(unit, afio, directory_handle_create_close, directory_handle, "Tests that afio::directory_handle::directory()'s parameters with relative paths work as expected", directory_handle_create_close_creation(directory_handle_create_close::test_kernel_directory_handle_relative))
+KERNELTEST_TEST_KERNEL(unit, llfio, directory_handle_create_close, directory_handle, "Tests that llfio::directory_handle::directory()'s parameters with absolute paths work as expected", directory_handle_create_close_creation(directory_handle_create_close::test_kernel_directory_handle_absolute))
+KERNELTEST_TEST_KERNEL(unit, llfio, directory_handle_create_close, directory_handle, "Tests that llfio::directory_handle::directory()'s parameters with relative paths work as expected", directory_handle_create_close_creation(directory_handle_create_close::test_kernel_directory_handle_relative))
diff --git a/test/tests/directory_handle_enumerate/kernel_directory_handle_enumerate.cpp.hpp b/test/tests/directory_handle_enumerate/kernel_directory_handle_enumerate.cpp.hpp
index fbdcc8ad..b4500928 100644
--- a/test/tests/directory_handle_enumerate/kernel_directory_handle_enumerate.cpp.hpp
+++ b/test/tests/directory_handle_enumerate/kernel_directory_handle_enumerate.cpp.hpp
@@ -26,9 +26,9 @@ Distributed under the Boost Software License, Version 1.0.
namespace directory_handle_enumerate
{
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> test_kernel_directory_handle_enumerate(AFIO_V2_NAMESPACE::span<AFIO_V2_NAMESPACE::directory_entry> *buffers, AFIO_V2_NAMESPACE::path_view glob, AFIO_V2_NAMESPACE::directory_handle::filter filtering)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::directory_handle::enumerate_info> test_kernel_directory_handle_enumerate(LLFIO_V2_NAMESPACE::span<LLFIO_V2_NAMESPACE::directory_entry> *buffers, LLFIO_V2_NAMESPACE::path_view glob, LLFIO_V2_NAMESPACE::directory_handle::filter filtering)
{
- OUTCOME_TRY(h, AFIO_V2_NAMESPACE::directory_handle::directory({}, "."));
+ OUTCOME_TRY(h, LLFIO_V2_NAMESPACE::directory_handle::directory({}, "."));
auto ret = h.enumerate(*buffers, glob, filtering);
h.close().value();
return ret;
diff --git a/test/tests/directory_handle_enumerate/runner.cpp b/test/tests/directory_handle_enumerate/runner.cpp
index 4e28c444..99bc10b7 100644
--- a/test/tests/directory_handle_enumerate/runner.cpp
+++ b/test/tests/directory_handle_enumerate/runner.cpp
@@ -27,20 +27,20 @@ Distributed under the Boost Software License, Version 1.0.
template <class U> inline void directory_handle_enumerate_(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
- using AFIO_V2_NAMESPACE::result;
- using AFIO_V2_NAMESPACE::path_view;
- using AFIO_V2_NAMESPACE::directory_entry;
- using AFIO_V2_NAMESPACE::directory_handle;
- using filter = AFIO_V2_NAMESPACE::directory_handle::filter;
+ using LLFIO_V2_NAMESPACE::result;
+ using LLFIO_V2_NAMESPACE::path_view;
+ using LLFIO_V2_NAMESPACE::directory_entry;
+ using LLFIO_V2_NAMESPACE::directory_handle;
+ using filter = LLFIO_V2_NAMESPACE::directory_handle::filter;
static directory_entry _entries[5];
- static AFIO_V2_NAMESPACE::span<directory_entry> entries(_entries);
+ static LLFIO_V2_NAMESPACE::span<directory_entry> entries(_entries);
// clang-format off
static const auto permuter(mt_permute_parameters<
result<void>,
parameters<
- AFIO_V2_NAMESPACE::span<directory_entry> *,
+ LLFIO_V2_NAMESPACE::span<directory_entry> *,
path_view,
filter
>,
@@ -124,4 +124,4 @@ template <class U> inline void directory_handle_enumerate_(U &&f)
check_results_with_boost_test(permuter, results);
}
-KERNELTEST_TEST_KERNEL(unit, afio, directory_handle_enumerate, directory_handle, "Tests that afio::directory_handle::enumerate's parameters work as expected", directory_handle_enumerate_(directory_handle_enumerate::test_kernel_directory_handle_enumerate))
+KERNELTEST_TEST_KERNEL(unit, llfio, directory_handle_enumerate, directory_handle, "Tests that llfio::directory_handle::enumerate's parameters work as expected", directory_handle_enumerate_(directory_handle_enumerate::test_kernel_directory_handle_enumerate))
diff --git a/test/tests/file_handle_create_close/kernel_async_file_handle.cpp.hpp b/test/tests/file_handle_create_close/kernel_async_file_handle.cpp.hpp
index 3c8ae225..278363cd 100644
--- a/test/tests/file_handle_create_close/kernel_async_file_handle.cpp.hpp
+++ b/test/tests/file_handle_create_close/kernel_async_file_handle.cpp.hpp
@@ -26,19 +26,19 @@ Distributed under the Boost Software License, Version 1.0.
namespace file_handle_create_close
{
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::async_file_handle> test_kernel_async_file_handle_absolute(AFIO_V2_NAMESPACE::async_file_handle::mode m, AFIO_V2_NAMESPACE::async_file_handle::creation c, AFIO_V2_NAMESPACE::async_file_handle::flag f)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::async_file_handle> test_kernel_async_file_handle_absolute(LLFIO_V2_NAMESPACE::async_file_handle::mode m, LLFIO_V2_NAMESPACE::async_file_handle::creation c, LLFIO_V2_NAMESPACE::async_file_handle::flag f)
{
- AFIO_V2_NAMESPACE::io_service service;
- auto h = AFIO_V2_NAMESPACE::async_file_handle::async_file(service, {}, "testfile.txt", m, c, AFIO_V2_NAMESPACE::async_file_handle::caching::all, f);
+ LLFIO_V2_NAMESPACE::io_service service;
+ auto h = LLFIO_V2_NAMESPACE::async_file_handle::async_file(service, {}, "testfile.txt", m, c, LLFIO_V2_NAMESPACE::async_file_handle::caching::all, f);
if(h) {
h.value().close().value(); }
return h;
}
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::async_file_handle> test_kernel_async_file_handle_relative(AFIO_V2_NAMESPACE::async_file_handle::mode m, AFIO_V2_NAMESPACE::async_file_handle::creation c, AFIO_V2_NAMESPACE::async_file_handle::flag f)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::async_file_handle> test_kernel_async_file_handle_relative(LLFIO_V2_NAMESPACE::async_file_handle::mode m, LLFIO_V2_NAMESPACE::async_file_handle::creation c, LLFIO_V2_NAMESPACE::async_file_handle::flag f)
{
- AFIO_V2_NAMESPACE::io_service service;
- OUTCOME_TRY(b, AFIO_V2_NAMESPACE::path_handle::path("."));
- auto h = AFIO_V2_NAMESPACE::async_file_handle::async_file(service, b, "testfile.txt", m, c, AFIO_V2_NAMESPACE::async_file_handle::caching::all, f);
+ LLFIO_V2_NAMESPACE::io_service service;
+ OUTCOME_TRY(b, LLFIO_V2_NAMESPACE::path_handle::path("."));
+ auto h = LLFIO_V2_NAMESPACE::async_file_handle::async_file(service, b, "testfile.txt", m, c, LLFIO_V2_NAMESPACE::async_file_handle::caching::all, f);
if(h) {
h.value().close().value(); }
b.close().value();
diff --git a/test/tests/file_handle_create_close/kernel_file_handle.cpp.hpp b/test/tests/file_handle_create_close/kernel_file_handle.cpp.hpp
index fbfb806f..6e41aeaf 100644
--- a/test/tests/file_handle_create_close/kernel_file_handle.cpp.hpp
+++ b/test/tests/file_handle_create_close/kernel_file_handle.cpp.hpp
@@ -26,17 +26,17 @@ Distributed under the Boost Software License, Version 1.0.
namespace file_handle_create_close
{
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::file_handle> test_kernel_file_handle_absolute(AFIO_V2_NAMESPACE::file_handle::mode m, AFIO_V2_NAMESPACE::file_handle::creation c, AFIO_V2_NAMESPACE::file_handle::flag f)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::file_handle> test_kernel_file_handle_absolute(LLFIO_V2_NAMESPACE::file_handle::mode m, LLFIO_V2_NAMESPACE::file_handle::creation c, LLFIO_V2_NAMESPACE::file_handle::flag f)
{
- auto h = AFIO_V2_NAMESPACE::file_handle::file({}, "testfile.txt", m, c, AFIO_V2_NAMESPACE::file_handle::caching::all, f);
+ auto h = LLFIO_V2_NAMESPACE::file_handle::file({}, "testfile.txt", m, c, LLFIO_V2_NAMESPACE::file_handle::caching::all, f);
if(h) {
h.value().close().value(); }
return h;
}
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::file_handle> test_kernel_file_handle_relative(AFIO_V2_NAMESPACE::file_handle::mode m, AFIO_V2_NAMESPACE::file_handle::creation c, AFIO_V2_NAMESPACE::file_handle::flag f)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::file_handle> test_kernel_file_handle_relative(LLFIO_V2_NAMESPACE::file_handle::mode m, LLFIO_V2_NAMESPACE::file_handle::creation c, LLFIO_V2_NAMESPACE::file_handle::flag f)
{
- OUTCOME_TRY(b, AFIO_V2_NAMESPACE::path_handle::path("."));
- auto h = AFIO_V2_NAMESPACE::file_handle::file(b, "testfile.txt", m, c, AFIO_V2_NAMESPACE::file_handle::caching::all, f);
+ OUTCOME_TRY(b, LLFIO_V2_NAMESPACE::path_handle::path("."));
+ auto h = LLFIO_V2_NAMESPACE::file_handle::file(b, "testfile.txt", m, c, LLFIO_V2_NAMESPACE::file_handle::caching::all, f);
if(h) {
h.value().close().value(); }
b.close().value();
diff --git a/test/tests/file_handle_create_close/runner.cpp b/test/tests/file_handle_create_close/runner.cpp
index a4808484..e33b0c09 100644
--- a/test/tests/file_handle_create_close/runner.cpp
+++ b/test/tests/file_handle_create_close/runner.cpp
@@ -28,10 +28,10 @@ Distributed under the Boost Software License, Version 1.0.
template <class U> inline void file_handle_create_close_creation(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
- using AFIO_V2_NAMESPACE::result;
- using file_handle = AFIO_V2_NAMESPACE::file_handle;
- static const result<void> no_such_file_or_directory = AFIO_V2_NAMESPACE::errc::no_such_file_or_directory;
- static const result<void> file_exists = AFIO_V2_NAMESPACE::errc::file_exists;
+ using LLFIO_V2_NAMESPACE::result;
+ using file_handle = LLFIO_V2_NAMESPACE::file_handle;
+ static const result<void> no_such_file_or_directory = LLFIO_V2_NAMESPACE::errc::no_such_file_or_directory;
+ static const result<void> file_exists = LLFIO_V2_NAMESPACE::errc::file_exists;
/* Set up a permuter which for every one of these parameter values listed,
tests with the value using the input workspace which should produce outcome
@@ -94,7 +94,7 @@ template <class U> inline void file_handle_create_close_creation(U &&f)
check_results_with_boost_test(permuter, results);
}
-KERNELTEST_TEST_KERNEL(unit, afio, file_handle_create_close, file_handle, "Tests that afio::file_handle::file()'s parameters with absolute paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_file_handle_absolute))
-KERNELTEST_TEST_KERNEL(unit, afio, file_handle_create_close, file_handle, "Tests that afio::file_handle::file()'s parameters with relative paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_file_handle_relative))
-KERNELTEST_TEST_KERNEL(unit, afio, file_handle_create_close, async_file_handle, "Tests that afio::async_file_handle::async_file()'s parameters with absolute paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_async_file_handle_absolute))
-KERNELTEST_TEST_KERNEL(unit, afio, file_handle_create_close, async_file_handle, "Tests that afio::async_file_handle::async_file()'s parameters with relative paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_async_file_handle_relative))
+KERNELTEST_TEST_KERNEL(unit, llfio, file_handle_create_close, file_handle, "Tests that llfio::file_handle::file()'s parameters with absolute paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_file_handle_absolute))
+KERNELTEST_TEST_KERNEL(unit, llfio, file_handle_create_close, file_handle, "Tests that llfio::file_handle::file()'s parameters with relative paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_file_handle_relative))
+KERNELTEST_TEST_KERNEL(unit, llfio, file_handle_create_close, async_file_handle, "Tests that llfio::async_file_handle::async_file()'s parameters with absolute paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_async_file_handle_absolute))
+KERNELTEST_TEST_KERNEL(unit, llfio, file_handle_create_close, async_file_handle, "Tests that llfio::async_file_handle::async_file()'s parameters with relative paths work as expected", file_handle_create_close_creation(file_handle_create_close::test_kernel_async_file_handle_relative))
diff --git a/test/tests/file_handle_lock_unlock.cpp b/test/tests/file_handle_lock_unlock.cpp
index ddb2a29c..141a5233 100644
--- a/test/tests/file_handle_lock_unlock.cpp
+++ b/test/tests/file_handle_lock_unlock.cpp
@@ -26,21 +26,21 @@ Distributed under the Boost Software License, Version 1.0.
static inline void TestFileHandleLockUnlock()
{
- namespace afio = AFIO_V2_NAMESPACE;
- afio::file_handle h1 = afio::file_handle::file({}, "temp", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::temporary, afio::file_handle::flag::unlink_on_first_close).value();
- afio::file_handle h2 = afio::file_handle::file({}, "temp", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::temporary, afio::file_handle::flag::unlink_on_first_close).value();
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ llfio::file_handle h1 = llfio::file_handle::file({}, "temp", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::temporary, llfio::file_handle::flag::unlink_on_first_close).value();
+ llfio::file_handle h2 = llfio::file_handle::file({}, "temp", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::temporary, llfio::file_handle::flag::unlink_on_first_close).value();
// Two exclusive locks not possible
{
auto _1 = h1.lock(0, 0, true, std::chrono::seconds(0));
BOOST_REQUIRE(!_1.has_error());
- if(h1.flags() & afio::file_handle::flag::byte_lock_insanity)
+ if(h1.flags() & llfio::file_handle::flag::byte_lock_insanity)
{
std::cout << "This platform has byte_lock_insanity so this test won't be useful, bailing out" << std::endl;
return;
}
auto _2 = h2.lock(0, 0, true, std::chrono::seconds(0));
BOOST_REQUIRE(_2.has_error());
- BOOST_CHECK(_2.error() == afio::errc::timed_out);
+ BOOST_CHECK(_2.error() == llfio::errc::timed_out);
}
// Two non-exclusive locks okay
{
@@ -55,8 +55,8 @@ static inline void TestFileHandleLockUnlock()
BOOST_REQUIRE(!_1.has_error());
auto _2 = h2.lock(0, 0, true, std::chrono::seconds(0));
BOOST_REQUIRE(_2.has_error());
- BOOST_CHECK(_2.error() == afio::errc::timed_out);
+ BOOST_CHECK(_2.error() == llfio::errc::timed_out);
}
}
-KERNELTEST_TEST_KERNEL(integration, afio, file_handle_lock_unlock, file_handle, "Tests that afio::file_handle's lock and unlock work as expected", TestFileHandleLockUnlock())
+KERNELTEST_TEST_KERNEL(integration, llfio, file_handle_lock_unlock, file_handle, "Tests that llfio::file_handle's lock and unlock work as expected", TestFileHandleLockUnlock())
diff --git a/test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp b/test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp
index 0bff154b..37c9b91f 100644
--- a/test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp
+++ b/test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp
@@ -26,10 +26,10 @@ Distributed under the Boost Software License, Version 1.0.
namespace map_handle_create_close
{
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::map_handle> test_kernel_map_handle(AFIO_V2_NAMESPACE::file_handle &backing, AFIO_V2_NAMESPACE::map_handle::size_type bytes, AFIO_V2_NAMESPACE::section_handle::flag m)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::map_handle> test_kernel_map_handle(LLFIO_V2_NAMESPACE::file_handle &backing, LLFIO_V2_NAMESPACE::map_handle::size_type bytes, LLFIO_V2_NAMESPACE::section_handle::flag m)
{
- auto sectionh = backing.is_valid() ? AFIO_V2_NAMESPACE::section_handle::section(backing, bytes, AFIO_V2_NAMESPACE::section_handle::flag::readwrite) : AFIO_V2_NAMESPACE::section_handle::section(bytes);
- auto h = AFIO_V2_NAMESPACE::map_handle::map(sectionh.value(), bytes, 0, m);
+ auto sectionh = backing.is_valid() ? LLFIO_V2_NAMESPACE::section_handle::section(backing, bytes, LLFIO_V2_NAMESPACE::section_handle::flag::readwrite) : LLFIO_V2_NAMESPACE::section_handle::section(bytes);
+ auto h = LLFIO_V2_NAMESPACE::map_handle::map(sectionh.value(), bytes, 0, m);
return h;
}
}
diff --git a/test/tests/map_handle_create_close/runner.cpp b/test/tests/map_handle_create_close/runner.cpp
index 4a3547fe..2198e7b8 100644
--- a/test/tests/map_handle_create_close/runner.cpp
+++ b/test/tests/map_handle_create_close/runner.cpp
@@ -27,10 +27,10 @@ Distributed under the Boost Software License, Version 1.0.
template <class U> inline void map_handle_create_close_(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
- using AFIO_V2_NAMESPACE::result;
- using AFIO_V2_NAMESPACE::file_handle;
- using AFIO_V2_NAMESPACE::section_handle;
- using AFIO_V2_NAMESPACE::map_handle;
+ using LLFIO_V2_NAMESPACE::result;
+ using LLFIO_V2_NAMESPACE::file_handle;
+ using LLFIO_V2_NAMESPACE::section_handle;
+ using LLFIO_V2_NAMESPACE::map_handle;
// Create a temporary file and put some text into it
file_handle temph;
@@ -72,7 +72,7 @@ template <class U> inline void map_handle_create_close_(U &&f)
{
// Create a temporary backing file
temph = file_handle::file({}, "tempfile", file_handle::mode::write, file_handle::creation::if_needed).value();
- temph.write(0, { {reinterpret_cast<const AFIO_V2_NAMESPACE::byte *>("I am some file data"), 19} }).value();
+ temph.write(0, { {reinterpret_cast<const LLFIO_V2_NAMESPACE::byte *>("I am some file data"), 19} }).value();
}
else
{
@@ -92,7 +92,7 @@ template <class U> inline void map_handle_create_close_(U &&f)
maph = std::move(testreturn.value());
}
// Need to close the map and any backing file as otherwise filesystem_setup won't be able to clear up the working dir on Windows
- auto onexit = AFIO_V2_NAMESPACE::undoer([&]{
+ auto onexit = LLFIO_V2_NAMESPACE::undoer([&]{
(void) maph.close();
(void) temph.close();
});
@@ -100,13 +100,13 @@ template <class U> inline void map_handle_create_close_(U &&f)
//#define KERNELTEST_CHECK(a, ...) BOOST_CHECK(__VA_ARGS__)
if (testreturn)
{
- AFIO_V2_NAMESPACE::byte *addr = maph.address();
+ LLFIO_V2_NAMESPACE::byte *addr = maph.address();
section_handle::flag flags = std::get<1>(std::get<1>(permuter[idx]));
KERNELTEST_CHECK(testreturn, maph.length() > 0);
KERNELTEST_CHECK(testreturn, addr != nullptr);
if (!(flags & section_handle::flag::nocommit) && addr != nullptr)
{
- AFIO_V2_NAMESPACE::byte buffer[64];
+ LLFIO_V2_NAMESPACE::byte buffer[64];
// Make sure the backing file is appearing in the map
if (use_file_backing && maph.is_readable())
{
@@ -116,21 +116,21 @@ template <class U> inline void map_handle_create_close_(U &&f)
if (use_file_backing)
{
auto b = maph.read(0, { {nullptr, 20} }).value();
- KERNELTEST_CHECK(testreturn, b[0].data == addr);
- KERNELTEST_CHECK(testreturn, b[0].len == 19); // reads do not read more than the backing length
+ KERNELTEST_CHECK(testreturn, b[0].data() == addr);
+ KERNELTEST_CHECK(testreturn, b[0].size() == 19); // reads do not read more than the backing length
}
else
{
auto b = maph.read(5, { {nullptr, 5000} }).value();
- KERNELTEST_CHECK(testreturn, b[0].data == addr+5); // NOLINT
- KERNELTEST_CHECK(testreturn, b[0].len == 4091);
+ KERNELTEST_CHECK(testreturn, b[0].data() == addr+5); // NOLINT
+ KERNELTEST_CHECK(testreturn, b[0].size() == 4091);
}
// If we are writable, write straight into the map
if (maph.is_writable() && addr)
{
memcpy(addr, "NIALL was here", 14);
// Make sure maph's write() works
- maph.write(1, { {reinterpret_cast<const AFIO_V2_NAMESPACE::byte *>("iall"), 4} });
+ maph.write(1, { {reinterpret_cast<const LLFIO_V2_NAMESPACE::byte *>("iall"), 4} });
// Make sure data written to the map turns up in the file
if (use_file_backing)
{
@@ -161,4 +161,4 @@ template <class U> inline void map_handle_create_close_(U &&f)
check_results_with_boost_test(permuter, results);
}
-KERNELTEST_TEST_KERNEL(unit, afio, map_handle_create_close, map_handle, "Tests that afio::map_handle's creation parameters work as expected", map_handle_create_close_(map_handle_create_close::test_kernel_map_handle))
+KERNELTEST_TEST_KERNEL(unit, llfio, map_handle_create_close, map_handle, "Tests that llfio::map_handle's creation parameters work as expected", map_handle_create_close_(map_handle_create_close::test_kernel_map_handle))
diff --git a/test/tests/mapped_span.cpp b/test/tests/mapped.cpp
index a7cf180b..98ca4d98 100644
--- a/test/tests/mapped_span.cpp
+++ b/test/tests/mapped.cpp
@@ -26,14 +26,14 @@ Distributed under the Boost Software License, Version 1.0.
static inline void TestMappedView1()
{
- using namespace AFIO_V2_NAMESPACE;
- using AFIO_V2_NAMESPACE::file_handle;
+ using namespace LLFIO_V2_NAMESPACE;
+ using LLFIO_V2_NAMESPACE::file_handle;
file_handle fh = file_handle::file({}, "testfile", file_handle::mode::write, file_handle::creation::if_needed, file_handle::caching::all, file_handle::flag::unlink_on_first_close).value();
fh.truncate(10000 * sizeof(int)).value();
section_handle sh(section_handle::section(fh).value());
- algorithm::mapped_span<int> v1(sh, 5);
- algorithm::mapped_span<int> v2(sh);
- algorithm::mapped_span<int> v3(50);
+ mapped<int> v1(sh, 5);
+ mapped<int> v2(sh);
+ mapped<int> v3(50);
BOOST_CHECK(v1.size() == 5);
BOOST_CHECK(v2.size() == 10000);
BOOST_CHECK(v3.size() == 50);
@@ -46,7 +46,7 @@ static inline void TestMappedView1()
try
{
// Overly large views must not extend the file until written to
- algorithm::mapped_span<int> v4(sh, 20000);
+ mapped<int> v4(sh, 20000);
BOOST_CHECK(fh.maximum_extent().value() == 10000 * sizeof(int));
}
catch(...)
@@ -62,9 +62,9 @@ static inline void TestMappedView1()
static inline void TestMappedView2()
{
- using namespace AFIO_V2_NAMESPACE;
- using AFIO_V2_NAMESPACE::file_handle;
- using AFIO_V2_NAMESPACE::byte;
+ using namespace LLFIO_V2_NAMESPACE;
+ using LLFIO_V2_NAMESPACE::file_handle;
+ using LLFIO_V2_NAMESPACE::byte;
{
std::error_code ec;
filesystem::remove("testfile", ec);
@@ -75,7 +75,7 @@ static inline void TestMappedView2()
byte *addr = mfh.address();
BOOST_CHECK(addr != nullptr);
- algorithm::mapped_span<int> v1(mfh);
+ map_view<int> v1(mfh);
BOOST_CHECK(v1.size() == 10000);
v1[0] = 78;
v1[9999] = 79;
@@ -83,38 +83,38 @@ static inline void TestMappedView2()
BOOST_CHECK(addr == mfh.address());
BOOST_CHECK(mfh.maximum_extent().value() == 20000 * sizeof(int));
BOOST_CHECK(mfh.underlying_file_maximum_extent().value() == 20000 * sizeof(int));
- v1 = algorithm::mapped_span<int>(mfh);
+ v1 = map_view<int>(mfh);
BOOST_CHECK(v1.size() == 20000);
BOOST_CHECK(v1[0] == 78);
BOOST_CHECK(v1[9999] == 79);
mfh.truncate(2 * 1024 * 1024).value(); // exceed reservation, cause hidden reserve
BOOST_CHECK(addr != nullptr);
- v1 = algorithm::mapped_span<int>(mfh);
+ v1 = map_view<int>(mfh);
BOOST_CHECK(v1.size() == 2 * 1024 * 1024 / sizeof(int));
BOOST_CHECK(v1[0] == 78);
BOOST_CHECK(v1[9999] == 79);
mfh.reserve(2 * 1024 * 1024).value();
BOOST_CHECK(mfh.address() != nullptr);
- v1 = algorithm::mapped_span<int>(mfh);
+ v1 = map_view<int>(mfh);
BOOST_CHECK(v1.size() == 2 * 1024 * 1024 / sizeof(int));
BOOST_CHECK(v1[0] == 78);
BOOST_CHECK(v1[9999] == 79);
mfh.truncate(1 * sizeof(int)).value();
BOOST_CHECK(mfh.address() != nullptr);
- v1 = algorithm::mapped_span<int>(mfh);
+ v1 = map_view<int>(mfh);
BOOST_CHECK(v1.size() == 1);
BOOST_CHECK(v1[0] == 78);
// Use a different handle to extend the file
mapped_file_handle mfh2 = mapped_file_handle::mapped_file(1024 * 1024, {}, "testfile", file_handle::mode::write, file_handle::creation::open_existing, file_handle::caching::all, file_handle::flag::unlink_on_first_close).value();
mfh2.truncate(10000 * sizeof(int)).value();
- v1 = algorithm::mapped_span<int>(mfh2);
+ v1 = map_view<int>(mfh2);
BOOST_CHECK(v1.size() == 10000);
v1[0] = 78;
v1[9999] = 79;
// On Windows this will have updated the mapping, on POSIX it will not, so prod POSIX
mfh.update_map().value();
- v1 = algorithm::mapped_span<int>(mfh);
+ v1 = map_view<int>(mfh);
BOOST_CHECK(v1.size() == 10000);
BOOST_CHECK(v1[0] == 78);
BOOST_CHECK(v1[9999] == 79);
@@ -127,7 +127,7 @@ static inline void TestMappedView2()
fh.truncate(10000 * sizeof(int)).value();
// On POSIX this will have updated the mapping, on Windows it will not, so prod Windows
mfh.update_map().value();
- v1 = algorithm::mapped_span<int>(mfh);
+ v1 = map_view<int>(mfh);
BOOST_REQUIRE(v1.size() == 10000);
BOOST_CHECK(v1[0] == 78);
BOOST_CHECK(v1[9999] == 0);
@@ -136,5 +136,5 @@ static inline void TestMappedView2()
BOOST_CHECK(mfh.address() == nullptr);
}
-KERNELTEST_TEST_KERNEL(integration, afio, algorithm, mapped_span1, "Tests that afio::algorithm::mapped_span works as expected", TestMappedView1())
-KERNELTEST_TEST_KERNEL(integration, afio, algorithm, mapped_span2, "Tests that afio::algorithm::mapped_span works as expected", TestMappedView2())
+KERNELTEST_TEST_KERNEL(integration, llfio, algorithm, mapped_span1, "Tests that llfio::mapped works as expected", TestMappedView1())
+KERNELTEST_TEST_KERNEL(integration, llfio, algorithm, mapped_span2, "Tests that llfio::map_view works as expected", TestMappedView2())
diff --git a/test/tests/path_discovery.cpp b/test/tests/path_discovery.cpp
index d9f1a150..ef9ae5e8 100644
--- a/test/tests/path_discovery.cpp
+++ b/test/tests/path_discovery.cpp
@@ -26,22 +26,22 @@ Distributed under the Boost Software License, Version 1.0.
static inline void TestPathDiscovery()
{
- namespace afio = AFIO_V2_NAMESPACE;
- auto raw_list = afio::path_discovery::all_temporary_directories();
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ auto raw_list = llfio::path_discovery::all_temporary_directories();
std::cout << "The raw list of temporary directory paths on this system are:" << std::endl;
for(auto &i : raw_list)
{
std::cout << " " << i.path << " (" << i.source << ")" << std::endl;
}
- auto verified_list = afio::path_discovery::verified_temporary_directories();
+ auto verified_list = llfio::path_discovery::verified_temporary_directories();
std::cout << "\nThe verified list of temporary directory paths on this system are:" << std::endl;
for(auto &i : verified_list)
{
std::cout << " " << i.path << " (" << i.source << ")" << std::endl;
}
- auto &storage_backed = afio::path_discovery::storage_backed_temporary_files_directory();
+ auto &storage_backed = llfio::path_discovery::storage_backed_temporary_files_directory();
if(storage_backed.is_valid())
{
std::cout << "\nThe storage backed temporary files directory chosen is:\n " << storage_backed.current_path().value() << std::endl;
@@ -51,7 +51,7 @@ static inline void TestPathDiscovery()
std::cout << "\nNo storage backed temporary files directory found!" << std::endl;
}
- auto &memory_backed = afio::path_discovery::memory_backed_temporary_files_directory();
+ auto &memory_backed = llfio::path_discovery::memory_backed_temporary_files_directory();
if(memory_backed.is_valid())
{
std::cout << "\nThe memory backed temporary files directory chosen is:\n " << memory_backed.current_path().value() << std::endl;
@@ -62,4 +62,4 @@ static inline void TestPathDiscovery()
}
}
-KERNELTEST_TEST_KERNEL(integration, afio, path_discovery, temp_directories, "Tests that afio::path_discovery works as expected", TestPathDiscovery())
+KERNELTEST_TEST_KERNEL(integration, llfio, path_discovery, temp_directories, "Tests that llfio::path_discovery works as expected", TestPathDiscovery())
diff --git a/test/tests/path_view.cpp b/test/tests/path_view.cpp
index 2fcd71cb..5648e8e2 100644
--- a/test/tests/path_view.cpp
+++ b/test/tests/path_view.cpp
@@ -24,55 +24,128 @@ Distributed under the Boost Software License, Version 1.0.
#include "../test_kernel_decl.hpp"
+template <class U> inline void CheckPathView(const LLFIO_V2_NAMESPACE::filesystem::path &p, const char *desc, U &&c)
+{
+ using LLFIO_V2_NAMESPACE::filesystem::path;
+ using LLFIO_V2_NAMESPACE::path_view;
+ auto r1 = c(p);
+ auto r2 = c(path_view(p));
+ BOOST_CHECK(r1 == r2);
+ if(r1 != r2)
+ {
+ std::cerr << "For " << desc << " with path " << p << "\n";
+ std::cerr << " filesystem::path returned " << r1 << "\n";
+ std::cerr << " path_view returned " << r2 << std::endl;
+ }
+}
+
+static inline void CheckPathView(const LLFIO_V2_NAMESPACE::filesystem::path &path)
+{
+ CheckPathView(path, "root_directory()", [](const auto &p) { return p.root_directory(); });
+ CheckPathView(path, "root_path()", [](const auto &p) { return p.root_path(); });
+ CheckPathView(path, "relative_path()", [](const auto &p) { return p.relative_path(); });
+ CheckPathView(path, "parent_path()", [](const auto &p) { return p.parent_path(); });
+ CheckPathView(path, "filename()", [](const auto &p) { return p.filename(); });
+ CheckPathView(path, "stem()", [](const auto &p) { return p.stem(); });
+ CheckPathView(path, "extension()", [](const auto &p) { return p.extension(); });
+}
+
static inline void TestPathView()
{
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
// path view has constexpr construction
- constexpr afio::path_view a, b("hello");
+ constexpr llfio::path_view a, b("hello");
BOOST_CHECK(a.empty());
BOOST_CHECK(!b.empty());
BOOST_CHECK(b == "hello");
// Globs
- BOOST_CHECK(afio::path_view("niall*").contains_glob());
+ BOOST_CHECK(llfio::path_view("niall*").contains_glob());
// Splitting
constexpr const char p[] = "/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir/0";
- afio::path_view e(p); // NOLINT
- afio::path_view f(e.filename());
+ llfio::path_view e(p); // NOLINT
+ llfio::path_view f(e.filename());
e.remove_filename();
BOOST_CHECK(e == "/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir");
BOOST_CHECK(f == "0");
#ifndef _WIN32
// cstr
- afio::path_view::c_str g(e);
+ llfio::path_view::c_str g(e);
BOOST_CHECK(g.buffer != p); // NOLINT
- afio::path_view::c_str h(f);
+ llfio::path_view::c_str h(f);
BOOST_CHECK(h.buffer == p + 70); // NOLINT
#endif
+ CheckPathView("/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir");
+#if 0
+ // I think we are standards conforming here, Dinkumware and libstdc++ are not
+ CheckPathView("/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir/");
+#endif
+ CheckPathView("/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir/0");
+ CheckPathView("/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir/0.txt");
+ CheckPathView("boostish/afio/programs/build_posix/testdir");
+#if 0
+ // I think we are standards conforming here, Dinkumware and libstdc++ are not
+ CheckPathView("boostish/afio/programs/build_posix/testdir/");
+#endif
+ CheckPathView("boostish/afio/programs/build_posix/testdir/0");
+ CheckPathView("boostish/afio/programs/build_posix/testdir/0.txt");
+ CheckPathView("0");
+ CheckPathView("0.txt");
+ CheckPathView("0.foo.txt");
+ CheckPathView(".0.foo.txt");
+#if 0
+ // I think we are standards conforming here, Dinkumware and libstdc++ are not
+ CheckPathView(".txt");
+ CheckPathView("/");
+ CheckPathView("//");
+#endif
+ CheckPathView("");
+ CheckPathView(".");
+ CheckPathView("..");
#ifdef _WIN32
// On Windows, UTF-8 and UTF-16 paths are equivalent and backslash conversion happens
- afio::path_view c("path/to"), d(L"path\\to");
+ llfio::path_view c("path/to"), d(L"path\\to");
BOOST_CHECK(c == d);
// Globs
- BOOST_CHECK(afio::path_view(L"niall*").contains_glob());
- BOOST_CHECK(afio::path_view("0123456789012345678901234567890123456789012345678901234567890123.deleted").is_afio_deleted());
- BOOST_CHECK(afio::path_view(L"0123456789012345678901234567890123456789012345678901234567890123.deleted").is_afio_deleted());
- BOOST_CHECK(!afio::path_view("0123456789012345678901234567890123456789g12345678901234567890123.deleted").is_afio_deleted());
+ BOOST_CHECK(llfio::path_view(L"niall*").contains_glob());
+ BOOST_CHECK(llfio::path_view("0123456789012345678901234567890123456789012345678901234567890123.deleted").is_llfio_deleted());
+ BOOST_CHECK(llfio::path_view(L"0123456789012345678901234567890123456789012345678901234567890123.deleted").is_llfio_deleted());
+ BOOST_CHECK(!llfio::path_view("0123456789012345678901234567890123456789g12345678901234567890123.deleted").is_llfio_deleted());
// Splitting
constexpr const wchar_t p2[] = L"\\mnt\\c\\Users\\ned\\Documents\\boostish\\afio\\programs\\build_posix\\testdir\\0";
- afio::path_view g(p2);
- afio::path_view h(g.filename());
+ llfio::path_view g(p2);
+ llfio::path_view h(g.filename());
g.remove_filename();
BOOST_CHECK(g == "\\mnt\\c\\Users\\ned\\Documents\\boostish\\afio\\programs\\build_posix\\testdir");
BOOST_CHECK(h == "0");
// cstr
- afio::path_view::c_str i(g, false);
+ llfio::path_view::c_str i(g, false);
BOOST_CHECK(i.buffer != p2);
- afio::path_view::c_str j(g, true);
+ llfio::path_view::c_str j(g, true);
BOOST_CHECK(j.buffer == p2);
- afio::path_view::c_str k(h, false);
+ llfio::path_view::c_str k(h, false);
BOOST_CHECK(k.buffer == p2 + 70);
+
+ CheckPathView(L"\\mnt\\c\\Users\\ned\\Documents\\boostish\\afio\\programs\\build_posix\\testdir\\0");
+ CheckPathView(L"C:\\Users\\ned\\Documents\\boostish\\afio\\programs\\build_posix\\testdir\\0");
+ CheckPathView("C:/Users/ned/Documents/boostish/afio/programs/build_posix/testdir/0.txt");
+ // CheckPathView(L"\\\\niall\\douglas.txt");
+ CheckPathView(L"\\!!\\niall\\douglas.txt");
+ CheckPathView(L"\\??\\niall\\douglas.txt");
+ CheckPathView(L"\\\\?\\niall\\douglas.txt");
+ CheckPathView(L"\\\\.\\niall\\douglas.txt");
+
+ // Handle NT kernel paths correctly
+ BOOST_CHECK(llfio::path_view(L"\\\\niall").is_absolute());
+ BOOST_CHECK(llfio::path_view(L"\\!!\\niall").is_absolute());
+ BOOST_CHECK(llfio::path_view(L"\\??\\niall").is_absolute());
+ BOOST_CHECK(llfio::path_view(L"\\\\?\\niall").is_absolute());
+ BOOST_CHECK(llfio::path_view(L"\\\\.\\niall").is_absolute());
+ // On Windows this is relative, on POSIX it is absolute
+ BOOST_CHECK(llfio::path_view("/niall").is_relative());
+#else
+ BOOST_CHECK(llfio::path_view("/niall").is_absolute());
#endif
}
-KERNELTEST_TEST_KERNEL(integration, afio, path_view, path_view, "Tests that afio::path_view() works as expected", TestPathView())
+KERNELTEST_TEST_KERNEL(integration, llfio, path_view, path_view, "Tests that llfio::path_view() works as expected", TestPathView())
diff --git a/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp b/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp
index 4c5e21ca..981ec067 100644
--- a/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp
+++ b/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp
@@ -26,9 +26,9 @@ Distributed under the Boost Software License, Version 1.0.
namespace section_handle_create_close
{
- AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::section_handle> test_kernel_section_handle(AFIO_V2_NAMESPACE::file_handle &backing, AFIO_V2_NAMESPACE::section_handle::extent_type maximum_size, AFIO_V2_NAMESPACE::section_handle::flag m)
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::section_handle> test_kernel_section_handle(LLFIO_V2_NAMESPACE::file_handle &backing, LLFIO_V2_NAMESPACE::section_handle::extent_type maximum_size, LLFIO_V2_NAMESPACE::section_handle::flag m)
{
- auto h = backing.is_valid() ? AFIO_V2_NAMESPACE::section_handle::section(backing, maximum_size, m) : AFIO_V2_NAMESPACE::section_handle::section(maximum_size, AFIO_V2_NAMESPACE::path_discovery::storage_backed_temporary_files_directory(), m);
+ auto h = backing.is_valid() ? LLFIO_V2_NAMESPACE::section_handle::section(backing, maximum_size, m) : LLFIO_V2_NAMESPACE::section_handle::section(maximum_size, LLFIO_V2_NAMESPACE::path_discovery::storage_backed_temporary_files_directory(), m);
return h;
}
}
diff --git a/test/tests/section_handle_create_close/runner.cpp b/test/tests/section_handle_create_close/runner.cpp
index 9b5d63f3..bcf19165 100644
--- a/test/tests/section_handle_create_close/runner.cpp
+++ b/test/tests/section_handle_create_close/runner.cpp
@@ -27,9 +27,9 @@ Distributed under the Boost Software License, Version 1.0.
template <class U> inline void section_handle_create_close_(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
- using AFIO_V2_NAMESPACE::result;
- using AFIO_V2_NAMESPACE::file_handle;
- using AFIO_V2_NAMESPACE::section_handle;
+ using LLFIO_V2_NAMESPACE::result;
+ using LLFIO_V2_NAMESPACE::file_handle;
+ using LLFIO_V2_NAMESPACE::section_handle;
// Create a temporary file and put some text into it
file_handle temph;
@@ -70,7 +70,7 @@ template <class U> inline void section_handle_create_close_(U &&f)
if (use_file_backing)
{
temph = file_handle::file({}, "tempfile", file_handle::mode::write, file_handle::creation::if_needed).value();
- temph.write(0, { {reinterpret_cast<const AFIO_V2_NAMESPACE::byte *>("niall is not here"), 17} }).value();
+ temph.write(0, { {reinterpret_cast<const LLFIO_V2_NAMESPACE::byte *>("niall is not here"), 17} }).value();
}
else
{
@@ -94,4 +94,4 @@ template <class U> inline void section_handle_create_close_(U &&f)
check_results_with_boost_test(permuter, results);
}
-KERNELTEST_TEST_KERNEL(unit, afio, section_handle_create_close, section_handle, "Tests that afio::section_handle's creation parameters work as expected", section_handle_create_close_(section_handle_create_close::test_kernel_section_handle))
+KERNELTEST_TEST_KERNEL(unit, llfio, section_handle_create_close, section_handle, "Tests that llfio::section_handle's creation parameters work as expected", section_handle_create_close_(section_handle_create_close::test_kernel_section_handle))
diff --git a/test/tests/shared_fs_mutex.cpp b/test/tests/shared_fs_mutex.cpp
index 9786e12d..60145f58 100644
--- a/test/tests/shared_fs_mutex.cpp
+++ b/test/tests/shared_fs_mutex.cpp
@@ -26,8 +26,8 @@ Distributed under the Boost Software License, Version 1.0.
#include "../test_kernel_decl.hpp"
-KERNELTEST_TEST_KERNEL(unit, afio, shared_fs_mutex, entity_endian, "Tests that afio::algorithm::shared_fs_mutex::entity_type has the right endian", [] {
- AFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type v(0, true);
+KERNELTEST_TEST_KERNEL(unit, llfio, shared_fs_mutex, entity_endian, "Tests that llfio::algorithm::shared_fs_mutex::entity_type has the right endian", [] {
+ LLFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type v(0, true);
BOOST_REQUIRE(v._init != 1UL); // NOLINT
}())
@@ -332,29 +332,29 @@ static inline void check_child_worker(const KERNELTEST_V1_NAMESPACE::child_worke
static std::string _TestSharedFSMutexCorrectnessChildWorker(KERNELTEST_V1_NAMESPACE::waitable_done &waitable, size_t childidx, shared_memory *shmem) // NOLINT
{
- namespace afio = AFIO_V2_NAMESPACE;
+ namespace llfio = LLFIO_V2_NAMESPACE;
++shmem->current_exclusive;
while(-1 != shmem->current_exclusive)
{
std::this_thread::yield();
}
- std::unique_ptr<afio::algorithm::shared_fs_mutex::shared_fs_mutex> lock;
+ std::unique_ptr<llfio::algorithm::shared_fs_mutex::shared_fs_mutex> lock;
switch(shmem->mutex_kind)
{
case shared_memory::mutex_kind_type::atomic_append:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::atomic_append>(afio::algorithm::shared_fs_mutex::atomic_append::fs_mutex_append({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::atomic_append>(llfio::algorithm::shared_fs_mutex::atomic_append::fs_mutex_append({}, "lockfile").value());
break;
case shared_memory::mutex_kind_type::byte_ranges:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::byte_ranges>(afio::algorithm::shared_fs_mutex::byte_ranges::fs_mutex_byte_ranges({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::byte_ranges>(llfio::algorithm::shared_fs_mutex::byte_ranges::fs_mutex_byte_ranges({}, "lockfile").value());
break;
case shared_memory::mutex_kind_type::safe_byte_ranges:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::safe_byte_ranges>(afio::algorithm::shared_fs_mutex::safe_byte_ranges::fs_mutex_safe_byte_ranges({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::safe_byte_ranges>(llfio::algorithm::shared_fs_mutex::safe_byte_ranges::fs_mutex_safe_byte_ranges({}, "lockfile").value());
break;
case shared_memory::mutex_kind_type::lock_files:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::lock_files>(afio::algorithm::shared_fs_mutex::lock_files::fs_mutex_lock_files(afio::path_handle::path(".").value()).value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::lock_files>(llfio::algorithm::shared_fs_mutex::lock_files::fs_mutex_lock_files(llfio::path_handle::path(".").value()).value());
break;
case shared_memory::mutex_kind_type::memory_map:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::memory_map<>>(afio::algorithm::shared_fs_mutex::memory_map<>::fs_mutex_map({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::memory_map<>>(llfio::algorithm::shared_fs_mutex::memory_map<>::fs_mutex_map({}, "lockfile").value());
break;
}
++shmem->current_shared;
@@ -367,7 +367,7 @@ static std::string _TestSharedFSMutexCorrectnessChildWorker(KERNELTEST_V1_NAMESP
{
if(shmem->testtype == shared_memory::test_type::exclusive || (shmem->testtype == shared_memory::test_type::both && childidx < 2))
{
- auto h = lock->lock(afio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type(0, true)).value();
+ auto h = lock->lock(llfio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type(0, true)).value();
long oldval = shmem->current_exclusive.exchange(static_cast<long>(childidx));
if(oldval != -1)
{
@@ -386,7 +386,7 @@ static std::string _TestSharedFSMutexCorrectnessChildWorker(KERNELTEST_V1_NAMESP
}
else if(shmem->testtype == shared_memory::test_type::shared || shmem->testtype == shared_memory::test_type::both)
{
- auto h = lock->lock(afio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type(0, false)).value();
+ auto h = lock->lock(llfio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type(0, false)).value();
long oldval = ++shmem->current_shared;
if(oldval > maxreaders)
{
@@ -403,10 +403,10 @@ static std::string _TestSharedFSMutexCorrectnessChildWorker(KERNELTEST_V1_NAMESP
return "ok, max concurrent readers was " + std::to_string(maxreaders);
}
static auto TestSharedFSMutexCorrectnessChildWorker = KERNELTEST_V1_NAMESPACE::register_child_worker("TestSharedFSMutexCorrectness", [](KERNELTEST_V1_NAMESPACE::waitable_done &waitable, size_t childidx, const char * /*unused*/) -> std::string { // NOLINT
- namespace afio = AFIO_V2_NAMESPACE;
- auto shared_mem_file = afio::file_handle::file({}, "shared_memory", afio::file_handle::mode::write, afio::file_handle::creation::open_existing, afio::file_handle::caching::temporary).value();
- auto shared_mem_file_section = afio::section_handle::section(shared_mem_file, sizeof(shared_memory), afio::section_handle::flag::readwrite).value();
- auto shared_mem_file_map = afio::map_handle::map(shared_mem_file_section).value();
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ auto shared_mem_file = llfio::file_handle::file({}, "shared_memory", llfio::file_handle::mode::write, llfio::file_handle::creation::open_existing, llfio::file_handle::caching::temporary).value();
+ auto shared_mem_file_section = llfio::section_handle::section(shared_mem_file, sizeof(shared_memory), llfio::section_handle::flag::readwrite).value();
+ auto shared_mem_file_map = llfio::map_handle::map(shared_mem_file_section).value();
auto *shmem = reinterpret_cast<shared_memory *>(shared_mem_file_map.address()); // NOLINT
return _TestSharedFSMutexCorrectnessChildWorker(waitable, childidx, shmem);
});
@@ -419,11 +419,11 @@ else. Verify shared allows other shared.
void TestSharedFSMutexCorrectness(shared_memory::mutex_kind_type mutex_kind, shared_memory::test_type testtype, bool threads_not_processes)
{
- namespace afio = AFIO_V2_NAMESPACE;
- auto shared_mem_file = afio::file_handle::file({}, "shared_memory", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::temporary, afio::file_handle::flag::unlink_on_first_close).value();
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ auto shared_mem_file = llfio::file_handle::file({}, "shared_memory", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::temporary, llfio::file_handle::flag::unlink_on_first_close).value();
shared_mem_file.truncate(sizeof(shared_memory)).value();
- auto shared_mem_file_section = afio::section_handle::section(shared_mem_file, sizeof(shared_memory), afio::section_handle::flag::readwrite).value();
- auto shared_mem_file_map = afio::map_handle::map(shared_mem_file_section).value();
+ auto shared_mem_file_section = llfio::section_handle::section(shared_mem_file, sizeof(shared_memory), llfio::section_handle::flag::readwrite).value();
+ auto shared_mem_file_map = llfio::map_handle::map(shared_mem_file_section).value();
auto *shmem = reinterpret_cast<shared_memory *>(shared_mem_file_map.address()); // NOLINT
shmem->current_shared = -static_cast<long>(std::thread::hardware_concurrency());
shmem->current_exclusive = -static_cast<long>(std::thread::hardware_concurrency()) - 1;
@@ -473,22 +473,22 @@ void TestSharedFSMutexCorrectness(shared_memory::mutex_kind_type mutex_kind, sha
}
}
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_byte_ranges, exclusives, "Tests that afio::algorithm::shared_fs_mutex::byte_ranges implementation implements exclusive locking", [] { TestSharedFSMutexCorrectness(shared_memory::byte_ranges, shared_memory::exclusive, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_byte_ranges, shared, "Tests that afio::algorithm::shared_fs_mutex::byte_ranges implementation implements shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::byte_ranges, shared_memory::shared, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_byte_ranges, both, "Tests that afio::algorithm::shared_fs_mutex::byte_ranges implementation implements a mixture of exclusive and shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::byte_ranges, shared_memory::both, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_byte_ranges, exclusives, "Tests that llfio::algorithm::shared_fs_mutex::byte_ranges implementation implements exclusive locking", [] { TestSharedFSMutexCorrectness(shared_memory::byte_ranges, shared_memory::exclusive, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_byte_ranges, shared, "Tests that llfio::algorithm::shared_fs_mutex::byte_ranges implementation implements shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::byte_ranges, shared_memory::shared, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_byte_ranges, both, "Tests that llfio::algorithm::shared_fs_mutex::byte_ranges implementation implements a mixture of exclusive and shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::byte_ranges, shared_memory::both, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_memory_map, exclusives, "Tests that afio::algorithm::shared_fs_mutex::memory_map implementation implements exclusive locking", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::exclusive, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_memory_map, shared, "Tests that afio::algorithm::shared_fs_mutex::memory_map implementation implements shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::shared, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_memory_map, both, "Tests that afio::algorithm::shared_fs_mutex::memory_map implementation implements a mixture of exclusive and shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::both, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_memory_map, exclusives, "Tests that llfio::algorithm::shared_fs_mutex::memory_map implementation implements exclusive locking", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::exclusive, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_memory_map, shared, "Tests that llfio::algorithm::shared_fs_mutex::memory_map implementation implements shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::shared, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_memory_map, both, "Tests that llfio::algorithm::shared_fs_mutex::memory_map implementation implements a mixture of exclusive and shared locking", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::both, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_safe_byte_ranges_process, exclusives, "Tests that afio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements exclusive locking with processes", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::exclusive, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_safe_byte_ranges_process, shared, "Tests that afio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements shared locking with processes", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::shared, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_safe_byte_ranges_process, both, "Tests that afio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements a mixture of exclusive and shared locking with processes",
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_safe_byte_ranges_process, exclusives, "Tests that llfio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements exclusive locking with processes", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::exclusive, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_safe_byte_ranges_process, shared, "Tests that llfio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements shared locking with processes", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::shared, false); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_safe_byte_ranges_process, both, "Tests that llfio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements a mixture of exclusive and shared locking with processes",
[] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::both, false); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_safe_byte_ranges_thread, exclusives, "Tests that afio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements exclusive locking with threads", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::exclusive, true); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_safe_byte_ranges_thread, shared, "Tests that afio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements shared locking with threads", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::shared, true); }())
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_safe_byte_ranges_thread, both, "Tests that afio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements a mixture of exclusive and shared locking with threads",
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_safe_byte_ranges_thread, exclusives, "Tests that llfio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements exclusive locking with threads", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::exclusive, true); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_safe_byte_ranges_thread, shared, "Tests that llfio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements shared locking with threads", [] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::shared, true); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_safe_byte_ranges_thread, both, "Tests that llfio::algorithm::shared_fs_mutex::safe_byte_ranges implementation implements a mixture of exclusive and shared locking with threads",
[] { TestSharedFSMutexCorrectness(shared_memory::memory_map, shared_memory::both, true); }())
/*
@@ -509,11 +509,11 @@ and destructing the lock. This should find interesting races in the more complex
*/
static void TestSharedFSMutexConstructDestruct(shared_memory::mutex_kind_type mutex_kind)
{
- namespace afio = AFIO_V2_NAMESPACE;
- auto shared_mem_file = afio::file_handle::file({}, "shared_memory", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::temporary, afio::file_handle::flag::unlink_on_first_close).value();
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ auto shared_mem_file = llfio::file_handle::file({}, "shared_memory", llfio::file_handle::mode::write, llfio::file_handle::creation::if_needed, llfio::file_handle::caching::temporary, llfio::file_handle::flag::unlink_on_first_close).value();
shared_mem_file.truncate(sizeof(shared_memory)).value();
- auto shared_mem_file_section = afio::section_handle::section(shared_mem_file, sizeof(shared_memory), afio::section_handle::flag::readwrite).value();
- auto shared_mem_file_map = afio::map_handle::map(shared_mem_file_section).value();
+ auto shared_mem_file_section = llfio::section_handle::section(shared_mem_file, sizeof(shared_memory), llfio::section_handle::flag::readwrite).value();
+ auto shared_mem_file_map = llfio::map_handle::map(shared_mem_file_section).value();
auto *shmem = reinterpret_cast<shared_memory *>(shared_mem_file_map.address()); // NOLINT
shmem->current_shared = -2;
shmem->current_exclusive = -3;
@@ -548,33 +548,33 @@ static void TestSharedFSMutexConstructDestruct(shared_memory::mutex_kind_type mu
}
static auto TestSharedFSMutexConstructDestructChildWorker = KERNELTEST_V1_NAMESPACE::register_child_worker("TestSharedFSMutexConstructDestruct", [](KERNELTEST_V1_NAMESPACE::waitable_done & /*unused*/, size_t /*unused*/, const char *params) -> std::string { // NOLINT
- namespace afio = AFIO_V2_NAMESPACE;
- std::unique_ptr<afio::algorithm::shared_fs_mutex::shared_fs_mutex> lock;
+ namespace llfio = LLFIO_V2_NAMESPACE;
+ std::unique_ptr<llfio::algorithm::shared_fs_mutex::shared_fs_mutex> lock;
auto mutex_kind = static_cast<shared_memory::mutex_kind_type>(atoi(params)); // NOLINT
switch(mutex_kind)
{
case shared_memory::mutex_kind_type::atomic_append:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::atomic_append>(afio::algorithm::shared_fs_mutex::atomic_append::fs_mutex_append({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::atomic_append>(llfio::algorithm::shared_fs_mutex::atomic_append::fs_mutex_append({}, "lockfile").value());
break;
case shared_memory::mutex_kind_type::byte_ranges:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::byte_ranges>(afio::algorithm::shared_fs_mutex::byte_ranges::fs_mutex_byte_ranges({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::byte_ranges>(llfio::algorithm::shared_fs_mutex::byte_ranges::fs_mutex_byte_ranges({}, "lockfile").value());
break;
case shared_memory::mutex_kind_type::safe_byte_ranges:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::safe_byte_ranges>(afio::algorithm::shared_fs_mutex::safe_byte_ranges::fs_mutex_safe_byte_ranges({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::safe_byte_ranges>(llfio::algorithm::shared_fs_mutex::safe_byte_ranges::fs_mutex_safe_byte_ranges({}, "lockfile").value());
break;
case shared_memory::mutex_kind_type::lock_files:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::lock_files>(afio::algorithm::shared_fs_mutex::lock_files::fs_mutex_lock_files(afio::path_handle::path(".").value()).value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::lock_files>(llfio::algorithm::shared_fs_mutex::lock_files::fs_mutex_lock_files(llfio::path_handle::path(".").value()).value());
break;
case shared_memory::mutex_kind_type::memory_map:
- lock = std::make_unique<afio::algorithm::shared_fs_mutex::memory_map<>>(afio::algorithm::shared_fs_mutex::memory_map<>::fs_mutex_map({}, "lockfile").value());
+ lock = std::make_unique<llfio::algorithm::shared_fs_mutex::memory_map<>>(llfio::algorithm::shared_fs_mutex::memory_map<>::fs_mutex_map({}, "lockfile").value());
break;
}
// Take a shared lock of a different entity
- auto h = lock->lock(afio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type(1, false)).value();
+ auto h = lock->lock(llfio::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type(1, false)).value();
return "ok";
});
-KERNELTEST_TEST_KERNEL(integration, afio, shared_fs_mutex_memory_map, construct_destruct, "Tests that afio::algorithm::shared_fs_mutex::memory_map constructor and destructor are race free", [] { TestSharedFSMutexConstructDestruct(shared_memory::memory_map); }())
+KERNELTEST_TEST_KERNEL(integration, llfio, shared_fs_mutex_memory_map, construct_destruct, "Tests that llfio::algorithm::shared_fs_mutex::memory_map constructor and destructor are race free", [] { TestSharedFSMutexConstructDestruct(shared_memory::memory_map); }())
/*
@@ -669,8 +669,8 @@ int main(int argc, char *argv[])
}
}
}
- AFIO_V2_NAMESPACE::filesystem::create_directory("shared_fs_mutex_testdir");
- AFIO_V2_NAMESPACE::filesystem::current_path("shared_fs_mutex_testdir");
+ LLFIO_V2_NAMESPACE::filesystem::create_directory("shared_fs_mutex_testdir");
+ LLFIO_V2_NAMESPACE::filesystem::current_path("shared_fs_mutex_testdir");
int result = QUICKCPPLIB_BOOST_UNIT_TEST_RUN_TESTS(argc, argv);
return result;
}
diff --git a/test/tests/symlink_handle_create_close/existing0/testfile.txt b/test/tests/symlink_handle_create_close/existing0/testfile.txt
new file mode 100644
index 00000000..e55f0f57
--- /dev/null
+++ b/test/tests/symlink_handle_create_close/existing0/testfile.txt
@@ -0,0 +1 @@
+niall \ No newline at end of file
diff --git a/test/tests/symlink_handle_create_close/existing1/testfile.txt b/test/tests/symlink_handle_create_close/existing1/testfile.txt
new file mode 100644
index 00000000..e55f0f57
--- /dev/null
+++ b/test/tests/symlink_handle_create_close/existing1/testfile.txt
@@ -0,0 +1 @@
+niall \ No newline at end of file
diff --git a/test/tests/symlink_handle_create_close/existing1/testlink b/test/tests/symlink_handle_create_close/existing1/testlink
new file mode 120000
index 00000000..62c74bcb
--- /dev/null
+++ b/test/tests/symlink_handle_create_close/existing1/testlink
@@ -0,0 +1 @@
+testfile.txt \ No newline at end of file
diff --git a/test/tests/symlink_handle_create_close/kernel_symlink_handle.cpp.hpp b/test/tests/symlink_handle_create_close/kernel_symlink_handle.cpp.hpp
new file mode 100644
index 00000000..04cb9098
--- /dev/null
+++ b/test/tests/symlink_handle_create_close/kernel_symlink_handle.cpp.hpp
@@ -0,0 +1,57 @@
+/* Test kernel for symlink_handle create and close
+(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
+File Created: Jul 2018
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "../../test_kernel_decl.hpp"
+
+namespace symlink_handle_create_close
+{
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::symlink_handle> test_kernel_symlink_handle_absolute(LLFIO_V2_NAMESPACE::symlink_handle::mode m, LLFIO_V2_NAMESPACE::symlink_handle::creation c, LLFIO_V2_NAMESPACE::symlink_handle::flag f)
+ {
+ auto h = LLFIO_V2_NAMESPACE::symlink_handle::symlink({}, "testlink", m, c, f);
+ if(h)
+ {
+ if(h.value().is_writable())
+ {
+ h.value().write("testfile.txt").value();
+ }
+ h.value().close().value();
+ }
+ return h;
+ }
+ LLFIO_TEST_KERNEL_DECL LLFIO_V2_NAMESPACE::result<LLFIO_V2_NAMESPACE::symlink_handle> test_kernel_symlink_handle_relative(LLFIO_V2_NAMESPACE::symlink_handle::mode m, LLFIO_V2_NAMESPACE::symlink_handle::creation c, LLFIO_V2_NAMESPACE::symlink_handle::flag f)
+ {
+ OUTCOME_TRY(b, LLFIO_V2_NAMESPACE::path_handle::path("."));
+ auto h = LLFIO_V2_NAMESPACE::symlink_handle::symlink(b, "testlink", m, c, f);
+ if(h)
+ {
+ if(h.value().is_writable())
+ {
+ h.value().write("testfile.txt").value();
+ }
+ h.value().close().value();
+ }
+ b.close().value();
+ return h;
+ }
+} // namespace file_handle_create_close
diff --git a/test/tests/symlink_handle_create_close/runner.cpp b/test/tests/symlink_handle_create_close/runner.cpp
new file mode 100644
index 00000000..b4a0b189
--- /dev/null
+++ b/test/tests/symlink_handle_create_close/runner.cpp
@@ -0,0 +1,82 @@
+/* Integration test kernel for symlink_handle create and close
+(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (22 commits)
+File Created: Jul 2018
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "kernel_symlink_handle.cpp.hpp"
+
+template <class U> inline void symlink_handle_create_close_creation(U &&f)
+{
+ using namespace KERNELTEST_V1_NAMESPACE;
+ using LLFIO_V2_NAMESPACE::result;
+ using symlink_handle = LLFIO_V2_NAMESPACE::symlink_handle;
+ static const result<void> no_such_file_or_directory = LLFIO_V2_NAMESPACE::errc::no_such_file_or_directory;
+ static const result<void> file_exists = LLFIO_V2_NAMESPACE::errc::file_exists;
+ static const result<void> function_not_supported = LLFIO_V2_NAMESPACE::errc::function_not_supported;
+ static const result<void> permission_denied = LLFIO_V2_NAMESPACE::errc::permission_denied;
+
+ assert(file_exists.error() == LLFIO_V2_NAMESPACE::errc::file_exists);
+
+ // clang-format off
+ static const auto permuter(mt_permute_parameters<
+ result<void>,
+ parameters<
+ typename symlink_handle::mode,
+ typename symlink_handle::creation,
+ typename symlink_handle::flag
+ >,
+ precondition::filesystem_setup_parameters,
+ postcondition::filesystem_comparison_structure_parameters
+ >(
+ {
+ // Does the mode parameter have the expected side effects?
+ { success(), { symlink_handle::mode::none, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { success(), { symlink_handle::mode::attr_read, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { success(), { symlink_handle::mode::attr_write, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing0" }, { "existing1" }},
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { function_not_supported, { symlink_handle::mode::append, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { success(), { symlink_handle::mode::attr_write, symlink_handle::creation::if_needed, symlink_handle::flag::none }, { "existing0" }, { "existing1" }},
+
+ // Does the creation parameter have the expected side effects?
+ { no_such_file_or_directory, { symlink_handle::mode::write, symlink_handle::creation::open_existing , symlink_handle::flag::none }, { "existing0" }, { "existing0" }},
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::open_existing , symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::only_if_not_exist, symlink_handle::flag::none }, { "existing0" }, { "existing1" }},
+ { file_exists, { symlink_handle::mode::write, symlink_handle::creation::only_if_not_exist, symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::if_needed , symlink_handle::flag::none }, { "existing0" }, { "existing1" }},
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::if_needed , symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+ { function_not_supported, { symlink_handle::mode::write, symlink_handle::creation::truncate , symlink_handle::flag::none }, { "existing1" }, { "existing1" }},
+
+ // Does the flag parameter have the expected side effects?
+ { success(), { symlink_handle::mode::write, symlink_handle::creation::open_existing, symlink_handle::flag::unlink_on_first_close }, { "existing1" }, { "existing0" }}
+ },
+ precondition::filesystem_setup(),
+ postcondition::filesystem_comparison_structure()
+ ));
+ // clang-format on
+
+ auto results = permuter(std::forward<U>(f));
+ check_results_with_boost_test(permuter, results);
+}
+
+KERNELTEST_TEST_KERNEL(unit, llfio, symlink_handle_create_close, symlink_handle, "Tests that llfio::symlink_handle::symlink()'s parameters with absolute paths work as expected", symlink_handle_create_close_creation(symlink_handle_create_close::test_kernel_symlink_handle_absolute))
+KERNELTEST_TEST_KERNEL(unit, llfio, symlink_handle_create_close, symlink_handle, "Tests that llfio::symlink_handle::symlink()'s parameters with relative paths work as expected", symlink_handle_create_close_creation(symlink_handle_create_close::test_kernel_symlink_handle_relative))
diff --git a/test/tests/trivial_vector.cpp b/test/tests/trivial_vector.cpp
index a5e90cb6..6cc5c60f 100644
--- a/test/tests/trivial_vector.cpp
+++ b/test/tests/trivial_vector.cpp
@@ -37,7 +37,7 @@ static inline void TestTrivialVector()
{
}
};
- using udt_vector = AFIO_V2_NAMESPACE::algorithm::trivial_vector<udt>;
+ using udt_vector = LLFIO_V2_NAMESPACE::algorithm::trivial_vector<udt>;
constexpr size_t _4kb = 4096 / sizeof(udt), _16kb = 16384 / sizeof(udt), _64kb = 65536 / sizeof(udt);
udt_vector v;
@@ -46,25 +46,25 @@ static inline void TestTrivialVector()
std::cout << "Resizing to 4Kb ..." << std::endl;
v.push_back(udt(5)); // first allocation of 4Kb
BOOST_CHECK(v.size() == 1);
- BOOST_CHECK(v.capacity() == AFIO_V2_NAMESPACE::utils::page_size() / sizeof(udt));
+ BOOST_CHECK(v.capacity() == LLFIO_V2_NAMESPACE::utils::page_size() / sizeof(udt));
BOOST_REQUIRE(v[0].v == 78);
std::cout << "Resizing to capacity ..." << std::endl;
v.resize(_4kb, udt(6)); // ought to be precisely 4Kb
BOOST_CHECK(v.size() == _4kb);
- BOOST_CHECK(v.capacity() == AFIO_V2_NAMESPACE::utils::round_up_to_page_size(4096) / sizeof(udt));
+ BOOST_CHECK(v.capacity() == LLFIO_V2_NAMESPACE::utils::round_up_to_page_size(4096) / sizeof(udt));
BOOST_REQUIRE(v[0].v == 78);
BOOST_REQUIRE(v[1].v == 79);
std::cout << "Resizing to 16Kb ..." << std::endl;
v.resize(_16kb, udt(7)); // 16Kb
BOOST_CHECK(v.size() == _16kb);
- BOOST_CHECK(v.capacity() == AFIO_V2_NAMESPACE::utils::round_up_to_page_size(16384) / sizeof(udt));
+ BOOST_CHECK(v.capacity() == LLFIO_V2_NAMESPACE::utils::round_up_to_page_size(16384) / sizeof(udt));
BOOST_REQUIRE(v[0].v == 78);
BOOST_REQUIRE(v[1].v == 79);
BOOST_REQUIRE(v[_4kb].v == 80);
std::cout << "Resizing to 64Kb ..." << std::endl;
v.resize(_64kb, udt(8)); // 64Kb
BOOST_CHECK(v.size() == _64kb);
- BOOST_CHECK(v.capacity() == AFIO_V2_NAMESPACE::utils::round_up_to_page_size(65536) / sizeof(udt));
+ BOOST_CHECK(v.capacity() == LLFIO_V2_NAMESPACE::utils::round_up_to_page_size(65536) / sizeof(udt));
BOOST_REQUIRE(v[0].v == 78);
BOOST_REQUIRE(v[1].v == 79);
BOOST_REQUIRE(v[_4kb].v == 80);
@@ -170,7 +170,7 @@ static inline void BenchmarkTrivialVector1()
idx = 0;
for(size_t items = 128; items < 16 * 1024 * 1024; items *= 2)
{
- AFIO_V2_NAMESPACE::algorithm::trivial_vector<udt> v2;
+ LLFIO_V2_NAMESPACE::algorithm::trivial_vector<udt> v2;
v2.reserve(1);
times[idx][2] = BenchmarkVector(v2, items);
++idx;
@@ -179,7 +179,7 @@ static inline void BenchmarkTrivialVector1()
{
csv << times[n][0] << "," << times[n][1] << "," << times[n][2] << std::endl;
std::cout << " std::vector<udt> inserts " << printKb(times[n][0]) << " in " << times[n][1] << " microseconds" << std::endl;
- std::cout << "afio::algorithm::trivial_vector<udt> inserts " << printKb(times[n][0]) << " in " << times[n][2] << " microseconds" << std::endl;
+ std::cout << "llfio::algorithm::trivial_vector<udt> inserts " << printKb(times[n][0]) << " in " << times[n][2] << " microseconds" << std::endl;
}
}
@@ -226,7 +226,7 @@ static inline void BenchmarkTrivialVector2()
for(size_t items = 128; items < 16 * 1024 * 1024; items *= 2)
{
{
- AFIO_V2_NAMESPACE::algorithm::trivial_vector<udt> v1;
+ LLFIO_V2_NAMESPACE::algorithm::trivial_vector<udt> v1;
v1.resize(items, 5);
begin = std::chrono::high_resolution_clock::now();
v1.resize(items * 2, 6);
@@ -239,10 +239,10 @@ static inline void BenchmarkTrivialVector2()
{
csv << times[n][0] << "," << times[n][1] << "," << times[n][2] << std::endl;
std::cout << " std::vector<udt> resizes " << printKb(times[n][0]) << " in " << times[n][1] << " microseconds" << std::endl;
- std::cout << "afio::algorithm::trivial_vector<udt> resizes " << printKb(times[n][0]) << " in " << times[n][2] << " microseconds" << std::endl;
+ std::cout << "llfio::algorithm::trivial_vector<udt> resizes " << printKb(times[n][0]) << " in " << times[n][2] << " microseconds" << std::endl;
}
}
-KERNELTEST_TEST_KERNEL(integration, afio, algorithm, trivial_vector, "Tests that afio::algorithm::trivial_vector works as expected", TestTrivialVector())
-KERNELTEST_TEST_KERNEL(integration, afio, algorithm, trivial_vector2, "Benchmarks afio::algorithm::trivial_vector against std::vector with push_back()", BenchmarkTrivialVector1())
-KERNELTEST_TEST_KERNEL(integration, afio, algorithm, trivial_vector3, "Benchmarks afio::algorithm::trivial_vector against std::vector with resize()", BenchmarkTrivialVector2())
+KERNELTEST_TEST_KERNEL(integration, llfio, algorithm, trivial_vector, "Tests that llfio::algorithm::trivial_vector works as expected", TestTrivialVector())
+KERNELTEST_TEST_KERNEL(integration, llfio, algorithm, trivial_vector2, "Benchmarks llfio::algorithm::trivial_vector against std::vector with push_back()", BenchmarkTrivialVector1())
+KERNELTEST_TEST_KERNEL(integration, llfio, algorithm, trivial_vector3, "Benchmarks llfio::algorithm::trivial_vector against std::vector with resize()", BenchmarkTrivialVector2())