void (@NotNull PersistentFSLoader loader) { List<VFSInitException> notClosedProperlyErrors = loader.problemsDuringLoad(NOT_CLOSED_PROPERLY); if (notClosedProperlyErrors.isEmpty()) { return; } PersistentFSRecordsStorage records = loader.recordsStorage(); ScannableDataEnumeratorEx<String> namesEnumerator = loader.namesStorage(); RefCountingContentStorage contentStorage = loader.contentsStorage(); ContentHashEnumerator contentHashEnumerator = loader.contentHashesEnumerator(); AbstractAttributesStorage attributesStorage = loader.attributesStorage(); try { int accumulatedErrors = records.getErrorsAccumulated(); if (accumulatedErrors > 0) { loader.problemsRecoveryFailed(notClosedProperlyErrors, HAS_ERRORS_IN_PREVIOUS_SESSION, accumulatedErrors + " errors accumulated in previous session -- too dangerous to recover"); } int namesEnumeratorErrors = 0; int attributesStorageErrors = 0; int contentEnumeratorErrors = 0; int totalErrors = 0; int maxAllocatedID = records.maxAllocatedID(); //Subset of VFSHealthChecker checks: for (int fileId = FSRecords.MIN_REGULAR_FILE_ID; fileId <= maxAllocatedID; fileId++) { int flags = records.getFlags(fileId); if (PersistentFSRecordAccessor.hasDeletedFlag(flags)) { continue; } int parentId = records.getParent(fileId); int nameId = records.getNameId(fileId); int contentId = records.getContentRecordId(fileId); int attributeRecordId = records.getAttributeRecordId(fileId); if (nameId == DataEnumerator.NULL_ID) { LOG.warn("[fileId: #" + fileId + "]: nameId=NULL -> remove the file record and schedule file refresh"); //remove file & schedule its invalidation, schedule parent for refresh: records.setFlags(fileId, flags | FREE_RECORD_FLAG); loader.postponeFileInvalidation(fileId); loader.postponeDirectoryRefresh(parentId); } else if (!nameResolvedSuccessfully(fileId, nameId, namesEnumerator)) { namesEnumeratorErrors++; totalErrors++; } if (!attributeRecordIsValid(fileId, attributeRecordId, attributesStorage)) { attributesStorageErrors++; totalErrors++; } if (contentId != DataEnumerator.NULL_ID) { if (!contentResolvedSuccessfully(fileId, contentId, contentStorage, contentHashEnumerator)) { contentEnumeratorErrors++; totalErrors++; } }//else: it is OK for contentId to be NULL if (totalErrors > MAX_ERRORS_TO_REPORT) { LOG.warn(totalErrors + " errors already detected -- no reason to continue, VFS needs rebuild anyway"); break; } } if (namesEnumeratorErrors == 0 && attributesStorageErrors == 0 && contentEnumeratorErrors == 0) { loader.problemsWereRecovered(notClosedProperlyErrors); return; } //Fail-safe: if following recovery procedures fail to rebuild VFS -- on restart, we'll short-circuit // the detailing checks records.setErrorsAccumulated(accumulatedErrors + totalErrors); if (namesEnumeratorErrors > 0) { loader.problemsRecoveryFailed(notClosedProperlyErrors, NAME_STORAGE_INCOMPLETE, namesEnumerator + " nameIds are not resolved"); } if (attributesStorageErrors > 0) { loader.problemsRecoveryFailed(notClosedProperlyErrors, ATTRIBUTES_STORAGE_CORRUPTED, attributesStorageErrors + " attributeRecordIds are unreadable"); } if (contentEnumeratorErrors > 0) { loader.problemsRecoveryFailed(notClosedProperlyErrors, CONTENT_STORAGES_INCOMPLETE, contentEnumeratorErrors + " contentIds are not resolved"); } } catch (Throwable t) { loader.problemsRecoveryFailed(notClosedProperlyErrors, UNRECOGNIZED, "Unexpected error during VFS consistency scan", t); } }