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_FILESYSTEMSTATCACHE_H
16#define LLVM_CLANG_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
23namespace clang {
24
25namespace vfs {
26class File;
27class FileSystem;
28}
29
30// FIXME: should probably replace this with vfs::Status
31struct 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.
48class FileSystemStatCache {
49  virtual void anchor();
50protected:
51  std::unique_ptr<FileSystemStatCache> NextStatCache;
52
53public:
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(FileSystemStatCache *Cache) {
78    NextStatCache.reset(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  FileSystemStatCache *takeNextStatCache() { return NextStatCache.release(); }
88
89protected:
90  // FIXME: The pointer here is a non-owning/optional reference to the
91  // unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but
92  // Optional needs some work to support references so this isn't possible yet.
93  virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
94                               std::unique_ptr<vfs::File> *F,
95                               vfs::FileSystem &FS) = 0;
96
97  LookupResult statChained(const char *Path, FileData &Data, bool isFile,
98                           std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
99    if (FileSystemStatCache *Next = getNextStatCache())
100      return Next->getStat(Path, Data, isFile, F, FS);
101
102    // If we hit the end of the list of stat caches to try, just compute and
103    // return it without a cache.
104    return get(Path, Data, isFile, F, nullptr, FS) ? CacheMissing : CacheExists;
105  }
106};
107
108/// \brief A stat "cache" that can be used by FileManager to keep
109/// track of the results of stat() calls that occur throughout the
110/// execution of the front end.
111class MemorizeStatCalls : public FileSystemStatCache {
112public:
113  /// \brief The set of stat() calls that have been seen.
114  llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
115
116  typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
117  iterator;
118
119  iterator begin() const { return StatCalls.begin(); }
120  iterator end() const { return StatCalls.end(); }
121
122  LookupResult getStat(const char *Path, FileData &Data, bool isFile,
123                       std::unique_ptr<vfs::File> *F,
124                       vfs::FileSystem &FS) override;
125};
126
127} // end namespace clang
128
129#endif
130