13#include "llvm/Support/Error.h"
14#include "llvm/Support/FileSystem.h"
15#include "llvm/Support/IOSandbox.h"
16#include "llvm/Support/LockFileManager.h"
17#include "llvm/Support/Path.h"
24 llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::OF_None);
29 if (PruneInterval <= 0 || PruneAfter <= 0)
33 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
36 llvm::sys::path::append(TimestampFile,
"modules.timestamp");
39 llvm::sys::fs::file_status StatBuf;
40 if (std::error_code EC = llvm::sys::fs::status(TimestampFile, StatBuf)) {
42 if (EC == std::errc::no_such_file_or_directory)
49 time_t TimestampModTime =
50 llvm::sys::toTimeT(StatBuf.getLastModificationTime());
51 time_t CurrentTime = time(
nullptr);
52 if (CurrentTime - TimestampModTime <= PruneInterval)
63 auto TryPruneFile = [&](StringRef FilePath) {
65 StringRef Filename = llvm::sys::path::filename(FilePath);
66 StringRef Extension = llvm::sys::path::extension(FilePath);
67 if (Extension !=
".pcm" && Extension !=
".timestamp" &&
68 Filename !=
"modules.idx")
72 if (Filename ==
"modules.timestamp")
77 if (llvm::sys::fs::status(FilePath, StatBuf))
81 time_t FileAccessTime = llvm::sys::toTimeT(StatBuf.getLastAccessedTime());
82 if (CurrentTime - FileAccessTime <= PruneAfter)
86 llvm::sys::fs::remove(FilePath);
89 std::string TimestampFilename = FilePath.str() +
".timestamp";
90 llvm::sys::fs::remove(TimestampFilename);
93 for (llvm::sys::fs::directory_iterator Dir(Path, EC), DirEnd;
94 Dir != DirEnd && !EC; Dir.increment(EC)) {
96 if (!llvm::sys::fs::is_directory(Dir->path())) {
97 TryPruneFile(Dir->path());
102 for (llvm::sys::fs::directory_iterator
File(Dir->path(), EC), FileEnd;
103 File != FileEnd && !EC;
File.increment(EC))
104 TryPruneFile(
File->path());
108 if (llvm::sys::fs::directory_iterator(Dir->path(), EC) ==
109 llvm::sys::fs::directory_iterator() &&
111 llvm::sys::fs::remove(Dir->path());
116 StringRef Extension = llvm::sys::path::extension(Path);
118 ModelPath +=
"-%%%%%%%%";
119 ModelPath += Extension;
125 if ((EC = llvm::sys::fs::createUniqueFile(ModelPath, FD, TmpPath))) {
126 if (EC != std::errc::no_such_file_or_directory)
129 StringRef Dir = llvm::sys::path::parent_path(Path);
130 if (std::error_code InnerEC = llvm::sys::fs::create_directories(Dir))
133 if ((EC = llvm::sys::fs::createUniqueFile(ModelPath, FD, TmpPath)))
138 llvm::raw_fd_ostream OS(FD,
true);
139 OS << Buffer.getBuffer();
142 if ((EC = llvm::sys::fs::rename(TmpPath, Path)))
151 llvm::sys::fs::openNativeFileForRead(
FileName);
153 return FD.takeError();
154 llvm::sys::fs::file_status Status;
155 if (std::error_code EC = llvm::sys::fs::status(*FD, Status))
156 return llvm::errorCodeToError(EC);
157 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf =
158 llvm::MemoryBuffer::getOpenFile(*FD,
FileName, Status.getSize(),
161 return llvm::errorCodeToError(Buf.getError());
162 Size = Status.getSize();
163 ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
164 return std::move(*Buf);
168class CrossProcessModuleCache :
public ModuleCache {
172 std::unique_ptr<llvm::AdvisoryLock>
173 getLock(StringRef ModuleFilename)
override {
174 return std::make_unique<llvm::LockFileManager>(ModuleFilename);
177 std::time_t getModuleTimestamp(StringRef ModuleFilename)
override {
179 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
181 std::string TimestampFilename =
183 llvm::sys::fs::file_status Status;
184 if (llvm::sys::fs::status(TimestampFilename, Status) != std::error_code{})
186 return llvm::sys::toTimeT(Status.getLastModificationTime());
189 void updateModuleTimestamp(StringRef ModuleFilename)
override {
191 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
195 llvm::raw_fd_ostream
OS(
197 llvm::sys::fs::OF_TextWithCRLF);
200 OS <<
"Timestamp file\n";
205 void maybePrune(StringRef Path, time_t PruneInterval,
206 time_t PruneAfter)
override {
208 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
213 InMemoryModuleCache &getInMemoryModuleCache()
override {
return InMemory; }
214 const InMemoryModuleCache &getInMemoryModuleCache()
const override {
218 std::error_code write(StringRef Path, llvm::MemoryBufferRef Buffer)
override {
220 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
225 Expected<std::unique_ptr<llvm::MemoryBuffer>>
226 read(StringRef
FileName, off_t &Size, time_t &ModTime)
override {
228 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
236 return std::make_shared<CrossProcessModuleCache>();
static void writeTimestampFile(StringRef TimestampFile)
Write a new timestamp file with the given path.
In-memory cache for modules.
The module cache used for compiling modules implicitly.
static std::string getTimestampFilename(StringRef FileName)
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
Expected< std::unique_ptr< llvm::MemoryBuffer > > readImpl(StringRef FileName, off_t &Size, time_t &ModTime)
Shared implementation of ModuleCache::read().
std::shared_ptr< ModuleCache > createCrossProcessModuleCache()
Creates new ModuleCache backed by a file system directory that may be operated on by multiple process...
void maybePruneImpl(StringRef Path, time_t PruneInterval, time_t PruneAfter)
Shared implementation of ModuleCache::maybePrune().
std::error_code writeImpl(StringRef Path, llvm::MemoryBufferRef Buffer)
Shared implementation of ModuleCache::write().