Home | History | Annotate | Download | only in Basic
      1 //===--- FileSystemStatCache.h - Caching for 'stat' calls -------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Defines the FileSystemStatCache interface.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
     16 #define LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
     17 
     18 #include "clang/Basic/LLVM.h"
     19 #include "llvm/ADT/StringMap.h"
     20 #include "llvm/Support/FileSystem.h"
     21 #include <memory>
     22 
     23 namespace clang {
     24 
     25 namespace vfs {
     26 class File;
     27 class FileSystem;
     28 }
     29 
     30 // FIXME: should probably replace this with vfs::Status
     31 struct FileData {
     32   std::string Name;
     33   uint64_t Size;
     34   time_t ModTime;
     35   llvm::sys::fs::UniqueID UniqueID;
     36   bool IsDirectory;
     37   bool IsNamedPipe;
     38   bool InPCH;
     39   bool IsVFSMapped; // FIXME: remove this when files support multiple names
     40   FileData()
     41       : Size(0), ModTime(0), IsDirectory(false), IsNamedPipe(false),
     42         InPCH(false), IsVFSMapped(false) {}
     43 };
     44 
     45 /// \brief Abstract interface for introducing a FileManager cache for 'stat'
     46 /// system calls, which is used by precompiled and pretokenized headers to
     47 /// improve performance.
     48 class FileSystemStatCache {
     49   virtual void anchor();
     50 protected:
     51   std::unique_ptr<FileSystemStatCache> NextStatCache;
     52 
     53 public:
     54   virtual ~FileSystemStatCache() {}
     55 
     56   enum LookupResult {
     57     CacheExists,   ///< We know the file exists and its cached stat data.
     58     CacheMissing   ///< We know that the file doesn't exist.
     59   };
     60 
     61   /// \brief Get the 'stat' information for the specified path, using the cache
     62   /// to accelerate it if possible.
     63   ///
     64   /// \returns \c true if the path does not exist or \c false if it exists.
     65   ///
     66   /// If isFile is true, then this lookup should only return success for files
     67   /// (not directories).  If it is false this lookup should only return
     68   /// success for directories (not files).  On a successful file lookup, the
     69   /// implementation can optionally fill in \p F with a valid \p File object and
     70   /// the client guarantees that it will close it.
     71   static bool get(const char *Path, FileData &Data, bool isFile,
     72                   std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache,
     73                   vfs::FileSystem &FS);
     74 
     75   /// \brief Sets the next stat call cache in the chain of stat caches.
     76   /// Takes ownership of the given stat cache.
     77   void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) {
     78     NextStatCache = std::move(Cache);
     79   }
     80 
     81   /// \brief Retrieve the next stat call cache in the chain.
     82   FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); }
     83 
     84   /// \brief Retrieve the next stat call cache in the chain, transferring
     85   /// ownership of this cache (and, transitively, all of the remaining caches)
     86   /// to the caller.
     87   std::unique_ptr<FileSystemStatCache> takeNextStatCache() {
     88     return std::move(NextStatCache);
     89   }
     90 
     91 protected:
     92   // FIXME: The pointer here is a non-owning/optional reference to the
     93   // unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but
     94   // Optional needs some work to support references so this isn't possible yet.
     95   virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
     96                                std::unique_ptr<vfs::File> *F,
     97                                vfs::FileSystem &FS) = 0;
     98 
     99   LookupResult statChained(const char *Path, FileData &Data, bool isFile,
    100                            std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
    101     if (FileSystemStatCache *Next = getNextStatCache())
    102       return Next->getStat(Path, Data, isFile, F, FS);
    103 
    104     // If we hit the end of the list of stat caches to try, just compute and
    105     // return it without a cache.
    106     return get(Path, Data, isFile, F, nullptr, FS) ? CacheMissing : CacheExists;
    107   }
    108 };
    109 
    110 /// \brief A stat "cache" that can be used by FileManager to keep
    111 /// track of the results of stat() calls that occur throughout the
    112 /// execution of the front end.
    113 class MemorizeStatCalls : public FileSystemStatCache {
    114 public:
    115   /// \brief The set of stat() calls that have been seen.
    116   llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
    117 
    118   typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
    119   iterator;
    120 
    121   iterator begin() const { return StatCalls.begin(); }
    122   iterator end() const { return StatCalls.end(); }
    123 
    124   LookupResult getStat(const char *Path, FileData &Data, bool isFile,
    125                        std::unique_ptr<vfs::File> *F,
    126                        vfs::FileSystem &FS) override;
    127 };
    128 
    129 } // end namespace clang
    130 
    131 #endif
    132