In FileManager: use full paths to unique files and directories on Windows,
since inodes are bogus abstraction on that platform. Patch by Argiris Kirtzidis! llvm-svn: 47535
This commit is contained in:
parent
a7d1ed4c98
commit
d87eef89c8
|
@ -22,6 +22,7 @@
|
||||||
#include "llvm/Bitcode/Serialize.h"
|
#include "llvm/Bitcode/Serialize.h"
|
||||||
#include "llvm/Bitcode/Deserialize.h"
|
#include "llvm/Bitcode/Deserialize.h"
|
||||||
#include "llvm/Support/Streams.h"
|
#include "llvm/Support/Streams.h"
|
||||||
|
#include "llvm/Config/config.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
// FIXME: Enhance libsystem to support inode and other fields.
|
// FIXME: Enhance libsystem to support inode and other fields.
|
||||||
|
@ -35,6 +36,107 @@ using namespace clang;
|
||||||
/// represent a dir name that doesn't exist on the disk.
|
/// represent a dir name that doesn't exist on the disk.
|
||||||
#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
|
#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
|
||||||
|
|
||||||
|
#ifdef LLVM_ON_WIN32
|
||||||
|
|
||||||
|
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\')
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static std::string GetFullPath(const char *relPath)
|
||||||
|
{
|
||||||
|
char *absPathStrPtr = _fullpath(NULL, relPath, 0);
|
||||||
|
assert(absPathStrPtr && "_fullpath() returned NULL!");
|
||||||
|
|
||||||
|
std::string absPath(absPathStrPtr);
|
||||||
|
|
||||||
|
free(absPathStrPtr);
|
||||||
|
return absPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileManager::UniqueDirContainer {
|
||||||
|
/// UniqueDirs - Cache from full path to existing directories/files.
|
||||||
|
///
|
||||||
|
llvm::StringMap<DirectoryEntry> UniqueDirs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
|
||||||
|
std::string FullPath(GetFullPath(Name));
|
||||||
|
return UniqueDirs.GetOrCreateValue(
|
||||||
|
FullPath.c_str(),
|
||||||
|
FullPath.c_str() + FullPath.size()
|
||||||
|
).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() { return UniqueDirs.size(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileManager::UniqueFileContainer {
|
||||||
|
/// UniqueFiles - Cache from full path to existing directories/files.
|
||||||
|
///
|
||||||
|
llvm::StringMap<FileEntry> UniqueFiles;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
|
||||||
|
std::string FullPath(GetFullPath(Name));
|
||||||
|
return UniqueFiles.GetOrCreateValue(
|
||||||
|
FullPath.c_str(),
|
||||||
|
FullPath.c_str() + FullPath.size()
|
||||||
|
).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() { return UniqueFiles.size(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/')
|
||||||
|
|
||||||
|
class FileManager::UniqueDirContainer {
|
||||||
|
/// UniqueDirs - Cache from ID's to existing directories/files.
|
||||||
|
///
|
||||||
|
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
|
||||||
|
return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() { return UniqueDirs.size(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileManager::UniqueFileContainer {
|
||||||
|
/// UniqueFiles - Cache from ID's to existing directories/files.
|
||||||
|
///
|
||||||
|
std::set<FileEntry> UniqueFiles;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
|
||||||
|
return
|
||||||
|
const_cast<FileEntry&>(
|
||||||
|
*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
|
||||||
|
StatBuf.st_ino)).first);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() { return UniqueFiles.size(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
FileManager::FileManager() : UniqueDirs(*new UniqueDirContainer),
|
||||||
|
UniqueFiles(*new UniqueFileContainer),
|
||||||
|
DirEntries(64), FileEntries(64), NextFileUID(0)
|
||||||
|
{
|
||||||
|
NumDirLookups = NumFileLookups = 0;
|
||||||
|
NumDirCacheMisses = NumFileCacheMisses = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileManager::~FileManager() {
|
||||||
|
delete &UniqueDirs;
|
||||||
|
delete &UniqueFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
||||||
/// returns null if the directory doesn't exist.
|
/// returns null if the directory doesn't exist.
|
||||||
///
|
///
|
||||||
|
@ -66,8 +168,7 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
|
||||||
|
|
||||||
// It exists. See if we have already opened a directory with the same inode.
|
// It exists. See if we have already opened a directory with the same inode.
|
||||||
// This occurs when one dir is symlinked to another, for example.
|
// This occurs when one dir is symlinked to another, for example.
|
||||||
DirectoryEntry &UDE =
|
DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf);
|
||||||
UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
|
|
||||||
|
|
||||||
NamedDirEnt.setValue(&UDE);
|
NamedDirEnt.setValue(&UDE);
|
||||||
if (UDE.getName()) // Already have an entry with this inode, return it.
|
if (UDE.getName()) // Already have an entry with this inode, return it.
|
||||||
|
@ -108,7 +209,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
|
||||||
// strip off everything after it.
|
// strip off everything after it.
|
||||||
// FIXME: this logic should be in sys::Path.
|
// FIXME: this logic should be in sys::Path.
|
||||||
const char *SlashPos = NameEnd-1;
|
const char *SlashPos = NameEnd-1;
|
||||||
while (SlashPos >= NameStart && SlashPos[0] != '/')
|
while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
|
||||||
--SlashPos;
|
--SlashPos;
|
||||||
|
|
||||||
const DirectoryEntry *DirInfo;
|
const DirectoryEntry *DirInfo;
|
||||||
|
@ -144,10 +245,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
|
||||||
|
|
||||||
// It exists. See if we have already opened a file with the same inode.
|
// It exists. See if we have already opened a file with the same inode.
|
||||||
// This occurs when one dir is symlinked to another, for example.
|
// This occurs when one dir is symlinked to another, for example.
|
||||||
FileEntry &UFE =
|
FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf);
|
||||||
const_cast<FileEntry&>(*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
|
|
||||||
StatBuf.st_ino)).first);
|
|
||||||
|
|
||||||
|
|
||||||
NamedFileEnt.setValue(&UFE);
|
NamedFileEnt.setValue(&UFE);
|
||||||
if (UFE.getName()) // Already have an entry with this inode, return it.
|
if (UFE.getName()) // Already have an entry with this inode, return it.
|
||||||
|
|
|
@ -48,6 +48,8 @@ class FileEntry {
|
||||||
friend class FileManager;
|
friend class FileManager;
|
||||||
public:
|
public:
|
||||||
FileEntry(dev_t device, ino_t inode) : Name(0), Device(device), Inode(inode){}
|
FileEntry(dev_t device, ino_t inode) : Name(0), Device(device), Inode(inode){}
|
||||||
|
// Add a default constructor for use with llvm::StringMap
|
||||||
|
FileEntry() : Name(0), Device(0), Inode(0) {}
|
||||||
|
|
||||||
const char *getName() const { return Name; }
|
const char *getName() const { return Name; }
|
||||||
off_t getSize() const { return Size; }
|
off_t getSize() const { return Size; }
|
||||||
|
@ -72,10 +74,14 @@ public:
|
||||||
/// names (e.g. symlinked) will be treated as a single file.
|
/// names (e.g. symlinked) will be treated as a single file.
|
||||||
///
|
///
|
||||||
class FileManager {
|
class FileManager {
|
||||||
/// UniqueDirs/UniqueFiles - Cache from ID's to existing directories/files.
|
|
||||||
|
class UniqueDirContainer;
|
||||||
|
class UniqueFileContainer;
|
||||||
|
|
||||||
|
/// UniqueDirs/UniqueFiles - Cache for existing directories/files.
|
||||||
///
|
///
|
||||||
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
|
UniqueDirContainer &UniqueDirs;
|
||||||
std::set<FileEntry> UniqueFiles;
|
UniqueFileContainer &UniqueFiles;
|
||||||
|
|
||||||
/// DirEntries/FileEntries - This is a cache of directory/file entries we have
|
/// DirEntries/FileEntries - This is a cache of directory/file entries we have
|
||||||
/// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
|
/// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
|
||||||
|
@ -91,10 +97,8 @@ class FileManager {
|
||||||
unsigned NumDirLookups, NumFileLookups;
|
unsigned NumDirLookups, NumFileLookups;
|
||||||
unsigned NumDirCacheMisses, NumFileCacheMisses;
|
unsigned NumDirCacheMisses, NumFileCacheMisses;
|
||||||
public:
|
public:
|
||||||
FileManager() : DirEntries(64), FileEntries(64), NextFileUID(0) {
|
FileManager();
|
||||||
NumDirLookups = NumFileLookups = 0;
|
~FileManager();
|
||||||
NumDirCacheMisses = NumFileCacheMisses = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
||||||
/// returns null if the directory doesn't exist.
|
/// returns null if the directory doesn't exist.
|
||||||
|
|
Loading…
Reference in New Issue