void ScanThread::scanDir( const RecordID& dirId, EntriesIt itEntriesBegin, EntriesIt itEntriesEnd) { if (shouldBreak()) { return; } Records oldRecords = db_.children(dirId); std::sort(oldRecords.begin(), oldRecords.end(), CmpByPath()); auto entriesRange = boost::make_iterator_range(itEntriesBegin, itEntriesEnd); for (const auto& entry : entriesRange) { scanEntry(getPath(entry), dirId, oldRecords, isRecursive(entry)); if (shouldBreak()) { return; } } for (const Record& missing : oldRecords) { try { delEntry(missing.first); } catch(std::exception const& ex) { std::cerr << "Failed to delete DB record for '" << missing.second.header.fileName << "' entry: " << ex.what() << std::endl; } } }
void ScanThread::scanEntry( const fs::path& path, const RecordID& parentID, Records& oldRecords, bool recursive) try { if (shouldBreak()) { return; } const bool isDir = fs::is_directory(path); Record newRecord = make_Record( NULL_RECORD_ID, RecordData(parentID, /*last write time*/0, isDir, path.string())); const std::pair<Records::iterator, Records::iterator> oldRange = std::equal_range(oldRecords.begin(), oldRecords.end(), newRecord, CmpByPath()); assert(std::distance(oldRange.first, oldRange.second) <= 1); const Records::iterator itOldRecord = oldRange.first != oldRange.second ? oldRange.first : oldRecords.end(); if (isDir && recursive) { // if new entry if (itOldRecord == oldRecords.end()) { addEntry(std::move(newRecord.second)); } } else // file { if (!isSupportedExtension(path)) { return; // unsupported extension } newRecord.second.header.lastWriteTime = fs::last_write_time(path); if (itOldRecord == oldRecords.end()) { addEntry(std::move(newRecord.second)); } else if(newRecord.second.header.lastWriteTime != itOldRecord->second.header.lastWriteTime) { newRecord.first = itOldRecord->first; replaceEntry(std::move(newRecord)); } } // record was processed, so removing from the list if (oldRecords.end() != itOldRecord) { oldRecords.erase(itOldRecord); } } catch(const fs::filesystem_error& ex) { std::cerr << "Failed to process filesystem element " << path << ": " << ex.what() << std::endl; // if the entry is inaccessible due to network resource down // it shouldn't be deleted from the database if (ex.code().value() != ENOENT) { const Record fakeRecord = make_Record(NULL_RECORD_ID, RecordData(NULL_RECORD_ID, 0, false, path.string())); const Records::iterator itOldRecord = std::lower_bound( oldRecords.begin(), oldRecords.end(), fakeRecord, CmpByPath()); // prevent record from deletion if (oldRecords.end() != itOldRecord) { oldRecords.erase(itOldRecord); } } } catch(const std::exception& ex) { std::cerr << "Failed to process filesystem element " << path << ": " << ex.what() << std::endl; }