Make sure file exists before importing it.

This commit is contained in:
Jacob Dufault 2017-08-15 22:39:50 -07:00
parent 49aca3038b
commit 7901653698
6 changed files with 58 additions and 24 deletions

View File

@ -818,6 +818,12 @@ struct IndexManager {
//} // namespace //} // namespace
enum class FileParseState {
NeedsParse,
DoesNotNeedParse,
BadFile
};
std::vector<Index_DoIdMap> DoParseFile( std::vector<Index_DoIdMap> DoParseFile(
Config* config, Config* config,
clang::Index* index, clang::Index* index,
@ -832,22 +838,31 @@ std::vector<Index_DoIdMap> DoParseFile(
if (previous_index) { if (previous_index) {
// If none of the dependencies have changed, skip parsing and just load from cache. // If none of the dependencies have changed, skip parsing and just load from cache.
auto file_needs_parse = [&](const std::string& path) { auto file_needs_parse = [&](const std::string& path) {
int64_t modification_timestamp = GetLastModificationTime(path); optional<int64_t> modification_timestamp = GetLastModificationTime(path);
if (!modification_timestamp)
return FileParseState::BadFile;
optional<int64_t> last_cached_modification = timestamp_manager->GetLastCachedModificationTime(cache_loader, path); optional<int64_t> last_cached_modification = timestamp_manager->GetLastCachedModificationTime(cache_loader, path);
if (!last_cached_modification || modification_timestamp != *last_cached_modification) { if (!last_cached_modification || modification_timestamp != *last_cached_modification) {
file_consumer_shared->Reset(path); file_consumer_shared->Reset(path);
return true; return FileParseState::NeedsParse;
} }
return false; return FileParseState::DoesNotNeedParse;
}; };
// Check timestamps and update |file_consumer_shared|. // Check timestamps and update |file_consumer_shared|.
bool needs_reparse = file_needs_parse(path); bool needs_reparse = false;
FileParseState path_state = file_needs_parse(path);
if (path_state == FileParseState::BadFile)
return result;
if (path_state == FileParseState::NeedsParse)
needs_reparse = true;
for (const std::string& dependency : previous_index->dependencies) { for (const std::string& dependency : previous_index->dependencies) {
assert(!dependency.empty()); assert(!dependency.empty());
if (file_needs_parse(dependency)) { if (file_needs_parse(dependency) == FileParseState::NeedsParse) {
LOG_S(INFO) << "Timestamp has changed for " << dependency; LOG_S(INFO) << "Timestamp has changed for " << dependency;
needs_reparse = true; needs_reparse = true;
// SUBTLE: Do not break here, as |file_consumer_shared| is updated // SUBTLE: Do not break here, as |file_consumer_shared| is updated
@ -890,6 +905,7 @@ std::vector<Index_DoIdMap> DoParseFile(
// TODO: We might be able to optimize perf by only copying for files in // TODO: We might be able to optimize perf by only copying for files in
// working_files. We can pass that same set of files to the indexer as // working_files. We can pass that same set of files to the indexer as
// well. We then default to a fast file-copy if not in working set. // well. We then default to a fast file-copy if not in working set.
bool loaded_primary = false;
std::vector<FileContents> file_contents; std::vector<FileContents> file_contents;
for (const auto& it : cache_loader->caches) { for (const auto& it : cache_loader->caches) {
const std::unique_ptr<IndexFile>& index = it.second; const std::unique_ptr<IndexFile>& index = it.second;
@ -900,6 +916,16 @@ std::vector<Index_DoIdMap> DoParseFile(
continue; continue;
} }
file_contents.push_back(FileContents(index->path, *index_content)); file_contents.push_back(FileContents(index->path, *index_content));
loaded_primary = loaded_primary || index->path == path;
}
if (!loaded_primary) {
optional<std::string> content = ReadContent(path);
if (!content) {
LOG_S(ERROR) << "Skipping index (file cannot be found): " << path;
return result;
}
file_contents.push_back(FileContents(path, *content));
} }
PerformanceImportFile perf; PerformanceImportFile perf;

View File

@ -128,7 +128,10 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
param->seen_files.push_back(file_name); param->seen_files.push_back(file_name);
// Set modification time. // Set modification time.
param->file_modification_times[file_name] = GetLastModificationTime(file_name); optional<int64_t> modification_time = GetLastModificationTime(file_name);
LOG_IF_S(ERROR, !modification_time) << "Failed fetching modification time for " << file_name;
if (modification_time)
param->file_modification_times[file_name] = *modification_time;
// Capture file contents in |param->file_contents| if it was not specified // Capture file contents in |param->file_contents| if it was not specified
// at the start of indexing. // at the start of indexing.

View File

@ -1,9 +1,14 @@
#pragma once #pragma once
#include <optional.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
using std::experimental::optional;
using std::experimental::nullopt;
struct PlatformMutex { struct PlatformMutex {
virtual ~PlatformMutex(); virtual ~PlatformMutex();
}; };
@ -37,7 +42,7 @@ bool TryMakeDirectory(const std::string& absolute_path);
void SetCurrentThreadName(const std::string& thread_name); void SetCurrentThreadName(const std::string& thread_name);
int64_t GetLastModificationTime(const std::string& absolute_path); optional<int64_t> GetLastModificationTime(const std::string& absolute_path);
void MoveFileTo(const std::string& destination, const std::string& source); void MoveFileTo(const std::string& destination, const std::string& source);
void CopyFileTo(const std::string& destination, const std::string& source); void CopyFileTo(const std::string& destination, const std::string& source);

View File

@ -166,20 +166,20 @@ void SetCurrentThreadName(const std::string& thread_name) {
#endif #endif
} }
int64_t GetLastModificationTime(const std::string& absolute_path) { optional<int64_t> GetLastModificationTime(const std::string& absolute_path) {
struct stat buf; struct stat buf;
if (stat(absolute_path.c_str(), &buf) != 0) { if (stat(absolute_path.c_str(), &buf) != 0) {
switch (errno) { switch (errno) {
case ENOENT: case ENOENT:
std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl; //std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl;
break; return nullopt;
case EINVAL: case EINVAL:
std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl; //std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl;
break; return nullopt;
default: default:
std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl; //std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl;
exit(1); //exit(1);
break; return nullopt;
} }
} }

View File

@ -184,20 +184,20 @@ void SetCurrentThreadName(const std::string& thread_name) {
__except (EXCEPTION_EXECUTE_HANDLER) {} __except (EXCEPTION_EXECUTE_HANDLER) {}
} }
int64_t GetLastModificationTime(const std::string& absolute_path) { optional<int64_t> GetLastModificationTime(const std::string& absolute_path) {
struct _stat buf; struct _stat buf;
if (_stat(absolute_path.c_str(), &buf) != 0) { if (_stat(absolute_path.c_str(), &buf) != 0) {
switch (errno) { switch (errno) {
case ENOENT: case ENOENT:
std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl; //std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl;
break; return nullopt;
case EINVAL: case EINVAL:
std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl; //std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl;
break; return nullopt;
default: default:
std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl; //std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl;
exit(1); //exit(1);
break; return nullopt;
} }
} }

View File

@ -305,7 +305,7 @@ QueryVarId GetQueryVarIdFromUsr(QueryDatabase* query_db, const Usr& usr) {
IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids) IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
: local_ids(local_ids) { : local_ids(local_ids) {
LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file; //LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file;
primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file); primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file);
cached_type_ids_.resize(local_ids.type_id_to_usr.size()); cached_type_ids_.resize(local_ids.type_id_to_usr.size());