[PATCH] D49530: [libc++] Implement Directory Entry Caching -- Sort of.

Eric Fiselier via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 18 21:14:29 PDT 2018


EricWF created this revision.
EricWF added reviewers: mclow.lists, gromer, ldionne, aaron.ballman.
Herald added a subscriber: christof.

This patch implements directory_entry caching *almost* as specified in P0317r1. However, I explicitly chose to deviate from the standard as I'll explain below.

The approach I decided to take is a fully caching one. When `refresh()` is called, the cache is populated by calls to `stat` and `lstat` as needed.
During directory iteration the cache is only populated with the `file_type` as reported by `readdir`.
The cache can be in the following states:

- `_Empty`: There is nothing in the cache (likely due to an error)
- `_IterSymlink`: Created by directory iteration when we walk onto a symlink only the symlink file type is known.
- `_IterNonSymlink`: Created by directory iteration when we walk onto a non-symlink. Both the regular file type and symlink file type are known.
- `_RefreshSymlink` and `_RefreshNonSymlink`: A full cache created by `refresh()`.  This case includes dead symlinks.
- `_RefreshSymlinkUnresolved`: A partial cache created by refresh when we fail to resolve the file pointed to by a symlink (likely due to permissions). Symlink attributes are cached, but attributes about the linked entity are not.

As mentioned, this implementation purposefully deviates from the standard. According to some readings of the specification, and the Windows filesystem implementation, the constructors and modifiers which don't pass an `error_code` must throw when the `directory_entry` points to a entity which doesn't exist. Note, this is different than the case where
we can't resolve whether the entity exists or not.

Instead of implementing the throwing behavior by default, I allow these functions to ignore ENOENT and ENOTDIR. However, like `status` and `symlink_status`, if the functions are given an error_code then it will be set the resulting error. I believe this behavior is much more user friendly. It's also worth noting that libstdc++'s implementation acts in the same manner (though perhaps unintentionally).

Users can opt-in to the strict error reporting required by the standard by providing the macro `_LIBCPP_ENABLE_FILESYSTEM_DIRECTORY_ENTRY_STRICT_ERROR_REPORTING`. See the `UsingLibcxx.rst` docs for more information and for motivating examples.

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0317r1.html


Repository:
  rCXX libc++

https://reviews.llvm.org/D49530

Files:
  docs/UsingLibcxx.rst
  include/experimental/filesystem
  src/experimental/filesystem/directory_iterator.cpp
  src/experimental/filesystem/filesystem_common.h
  src/experimental/filesystem/filesystem_time_helper.h
  src/experimental/filesystem/operations.cpp
  test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp
  test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh_hard_errors_disabled.pass.cpp
  test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh_hard_errors_enabled.pass.cpp
  test/libcxx/experimental/filesystem/convert_file_time.sh.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp
  test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp
  test/support/filesystem_test_helper.hpp
  test/support/rapid-cxx-test.hpp
  www/cxx1z_status.html

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D49530.156207.patch
Type: text/x-patch
Size: 141427 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180719/fa6b0b25/attachment-0001.bin>


More information about the cfe-commits mailing list