FileSystemStatCache.h revision 263508
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/OwningPtr.h"
20#include "llvm/ADT/StringMap.h"
21#include "llvm/Support/FileSystem.h"
22#include <sys/stat.h>
23#include <sys/types.h>
24
25namespace clang {
26
27struct FileData {
28  uint64_t Size;
29  time_t ModTime;
30  llvm::sys::fs::UniqueID UniqueID;
31  bool IsDirectory;
32  bool IsNamedPipe;
33  bool InPCH;
34};
35
36/// \brief Abstract interface for introducing a FileManager cache for 'stat'
37/// system calls, which is used by precompiled and pretokenized headers to
38/// improve performance.
39class FileSystemStatCache {
40  virtual void anchor();
41protected:
42  OwningPtr<FileSystemStatCache> NextStatCache;
43
44public:
45  virtual ~FileSystemStatCache() {}
46
47  enum LookupResult {
48    CacheExists,   ///< We know the file exists and its cached stat data.
49    CacheMissing   ///< We know that the file doesn't exist.
50  };
51
52  /// \brief Get the 'stat' information for the specified path, using the cache
53  /// to accelerate it if possible.
54  ///
55  /// \returns \c true if the path does not exist or \c false if it exists.
56  ///
57  /// If isFile is true, then this lookup should only return success for files
58  /// (not directories).  If it is false this lookup should only return
59  /// success for directories (not files).  On a successful file lookup, the
60  /// implementation can optionally fill in FileDescriptor with a valid
61  /// descriptor and the client guarantees that it will close it.
62  static bool get(const char *Path, FileData &Data, bool isFile,
63                  int *FileDescriptor, FileSystemStatCache *Cache);
64
65  /// \brief Sets the next stat call cache in the chain of stat caches.
66  /// Takes ownership of the given stat cache.
67  void setNextStatCache(FileSystemStatCache *Cache) {
68    NextStatCache.reset(Cache);
69  }
70
71  /// \brief Retrieve the next stat call cache in the chain.
72  FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); }
73
74  /// \brief Retrieve the next stat call cache in the chain, transferring
75  /// ownership of this cache (and, transitively, all of the remaining caches)
76  /// to the caller.
77  FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); }
78
79protected:
80  virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
81                               int *FileDescriptor) = 0;
82
83  LookupResult statChained(const char *Path, FileData &Data, bool isFile,
84                           int *FileDescriptor) {
85    if (FileSystemStatCache *Next = getNextStatCache())
86      return Next->getStat(Path, Data, isFile, FileDescriptor);
87
88    // If we hit the end of the list of stat caches to try, just compute and
89    // return it without a cache.
90    return get(Path, Data, isFile, FileDescriptor, 0) ? CacheMissing
91                                                      : CacheExists;
92  }
93};
94
95/// \brief A stat "cache" that can be used by FileManager to keep
96/// track of the results of stat() calls that occur throughout the
97/// execution of the front end.
98class MemorizeStatCalls : public FileSystemStatCache {
99public:
100  /// \brief The set of stat() calls that have been seen.
101  llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
102
103  typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
104  iterator;
105
106  iterator begin() const { return StatCalls.begin(); }
107  iterator end() const { return StatCalls.end(); }
108
109  virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
110                               int *FileDescriptor);
111};
112
113} // end namespace clang
114
115#endif
116