Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
enumerate (metadata first non throwing)

Synchronous directory enumeration after a preceding operation.

Description

By default dir() returns shared handles i.e. dir( foo) and dir( foo) will return the exact same handle, and therefore enumerating not all of the entries at once is a race condition. The solution is to either set maxitems to a value large enough to guarantee a directory will be enumerated in a single shot, or to open a separate directory handle using the file_flags::unique_directory_handle flag. Note that setting maxitems=1 will often cause a buffer space exhaustion, causing a second syscall with an enlarged buffer. This is because AFIO cannot know if the allocated buffer can hold all of the filename being retrieved, so it may have to retry. Put another way, setting maxitems=1 will give you the worst performance possible, whereas maxitems=2 will probably only return one item most of the time. Related types: enumerate_req, directory_entry, stat_t

Synopsis
std::pair<std::vector<directory_entry>, bool> enumerate(error_code & _ec, future<> _precondition, metadata_flags _metadata,
                                                            size_t _maxitems = 2, bool _restart = true, path _glob = path(),
                                                            enumerate_req::filter _filtering = enumerate_req::filter::fastdeleted)
Parameters

Type

Concept

Name

Description

error_code &

_ec

Error code to set.

future<>

_precondition

The precondition to use.

metadata_flags

_metadata

The metadata to prefetch for each item enumerated. AFIO may fetch more metadata than requested if it is cost free.

size_t

_maxitems

The maximum number of items to return in this request. Note that setting to one will often invoke two syscalls.

bool

_restart

Restarts the enumeration for this open directory handle.

path

_glob

An optional shell glob by which to filter the items returned. Done kernel side on Windows, user side on POSIX.

enumerate_req::filter

_filtering

Any filtering you want AFIO to do for you.

Returns

A vector of results and a bool indicating if there is more.

Header

#include <boost/afio/v2/afio.hpp>

Race Guarantees

Operating system Race guarantees under a changing file system
FreeBSD, Linux, OS X Race free per batch of up to maxitems for ino and type only. Remember that many filing systems will recycle inodes such that a created file will get the inode of a just deleted file, so comparing inodes for equivalence to a direntry() won't help you.
Windows Race free per batch of up to maxitems for ino, type, atim, mtim, ctim, size, allocated, birthtim, sparse, compressed.

Complexity

Amortised O(1) to dispatch. Amortised O(M) to complete where M is the average number of entries in each directory.

Exception Model

Propagates the exception of any input precondition with an errored state at the point of dispatch, and throws a std::invalid_argument if any inputs have values which could not possibly be correct. Note that error code returning functions may still throw exceptions e.g. failure to allocate memory.

Example
  boost::afio::current_dispatcher_guard h(boost::afio::make_dispatcher().get());

  // Schedule an opening of the root directory
  boost::afio::future<> rootdir(boost::afio::async_dir("/"));

  std::pair<std::vector<boost::afio::directory_entry>, bool> list;
  // This is used to reset the enumeration to the start
  bool restart = true;
  do
  {
    // Schedule an enumeration of an open directory handle
    boost::afio::future<std::pair<std::vector<boost::afio::directory_entry>, bool>>
    enumeration(boost::afio::async_enumerate(
    rootdir,
    /* This is the maximum entries to enumerate. Note
    the use of compatibility_maximum() which is the
    same value your libc uses. The problem with smaller
    enumerations is that the directory contents can change
    out from underneath you more frequently. */
    boost::afio::directory_entry::compatibility_maximum(),
    /* True if to reset enumeration */
    restart));
    restart = false;

    // People using AFIO often forget that futures can be waited
    // on normally without needing to wait on the op handle
    list = enumeration.get();
    for(boost::afio::directory_entry &i : list.first)
    {
#ifdef WIN32
      std::wcout << i.name();
#else  /*_ defined(WIN32) _*/
      std::cout << i.name();
#endif  /*_ defined(WIN32) _*/
      std::cout << " type " << static_cast<int>(i.st_type()) << std::endl;
    }
  } while(list.second);


PrevUpHomeNext