| 1822 | } |
| 1823 | |
| 1824 | Status TmpFileGroup::RecoverWriteError( |
| 1825 | TmpWriteHandle* handle, const Status& write_status) { |
| 1826 | DCHECK(!write_status.ok()); |
| 1827 | DCHECK(handle->file_ != nullptr); |
| 1828 | |
| 1829 | // We can't recover from cancellation or memory limit exceeded. |
| 1830 | if (write_status.IsCancelled() || write_status.IsMemLimitExceeded()) { |
| 1831 | return write_status; |
| 1832 | } |
| 1833 | |
| 1834 | // We don't recover the errors generated during spilling to a remote file. |
| 1835 | if (handle->file_->disk_type() != io::DiskFileType::LOCAL) { |
| 1836 | return write_status; |
| 1837 | } |
| 1838 | |
| 1839 | // Save and report the error before retrying so that the failure isn't silent. |
| 1840 | { |
| 1841 | lock_guard<SpinLock> lock(lock_); |
| 1842 | scratch_errors_.push_back(write_status); |
| 1843 | if (handle->file_->Blacklist(write_status.msg())) { |
| 1844 | DCHECK_LT(num_blacklisted_files_, tmp_files_.size()); |
| 1845 | ++num_blacklisted_files_; |
| 1846 | if (num_blacklisted_files_ == tmp_files_.size()) { |
| 1847 | // Check if all errors are 'blacklistable'. |
| 1848 | bool are_all_blacklistable_errors = true; |
| 1849 | for (Status& err : scratch_errors_) { |
| 1850 | if (!ErrorConverter::IsBlacklistableError(err)) { |
| 1851 | are_all_blacklistable_errors = false; |
| 1852 | break; |
| 1853 | } |
| 1854 | } |
| 1855 | if (are_all_blacklistable_errors) spilling_disk_faulty_ = true; |
| 1856 | } |
| 1857 | } |
| 1858 | } |
| 1859 | |
| 1860 | // Do not retry cancelled writes or propagate the error, simply return CANCELLED. |
| 1861 | if (handle->is_cancelled_) return Status::CancelledInternal("TmpFileMgr write"); |
| 1862 | |
| 1863 | TmpFile* tmp_file; |
| 1864 | int64_t file_offset; |
| 1865 | // Discard the scratch file range - we will not reuse ranges from a bad file. |
| 1866 | // Choose another file to try. Blacklisting ensures we don't retry the same file. |
| 1867 | // If this fails, the status will include all the errors in 'scratch_errors_'. |
| 1868 | RETURN_IF_ERROR(AllocateSpace(handle->on_disk_len(), &tmp_file, &file_offset)); |
| 1869 | return handle->RetryWrite(io_ctx_.get(), tmp_file, file_offset); |
| 1870 | } |
| 1871 | |
| 1872 | Status TmpFileGroup::ScratchAllocationFailedStatus( |
| 1873 | const vector<int>& at_capacity_dirs) { |
nothing calls this directly
no test coverage detected