Report an error when disk is full
Previously packaging completes successfully without any error or warning. With the fix, an error will be reported if write fails. It may appear as "Cannot close file error" as we use threaded IO, which could delay the error reporting until Close() call, so the user of the File API needs to make sure Close() returns successfully. Also fixed a deadlock in threaded_io_file if internal_file->Write fails. Fixes #160 Change-Id: I17f945150fb4021d2dcdbe784e557673f53ca583
This commit is contained in:
parent
7627871428
commit
9c861d03f7
|
@ -250,8 +250,10 @@ bool File::WriteStringToFile(const char* file_name,
|
||||||
<< contents.size() << " bytes.";
|
<< contents.size() << " bytes.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!file->Flush()) {
|
if (!file.release()->Close()) {
|
||||||
LOG(ERROR) << "Failed to flush the file '" << file_name << "'.";
|
LOG(ERROR)
|
||||||
|
<< "Failed to close file '" << file_name
|
||||||
|
<< "', possibly file permission issue or running out of disk space.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -302,6 +304,12 @@ bool File::Copy(const char* from_file_name, const char* to_file_name) {
|
||||||
|
|
||||||
total_bytes_written += bytes_written;
|
total_bytes_written += bytes_written;
|
||||||
}
|
}
|
||||||
|
if (!output_file.release()->Close()) {
|
||||||
|
LOG(ERROR)
|
||||||
|
<< "Failed to close file '" << to_file_name
|
||||||
|
<< "', possibly file permission issue or running out of disk space.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,13 +37,25 @@ bool LocalFile::Close() {
|
||||||
int64_t LocalFile::Read(void* buffer, uint64_t length) {
|
int64_t LocalFile::Read(void* buffer, uint64_t length) {
|
||||||
DCHECK(buffer != NULL);
|
DCHECK(buffer != NULL);
|
||||||
DCHECK(internal_file_ != NULL);
|
DCHECK(internal_file_ != NULL);
|
||||||
return fread(buffer, sizeof(char), length, internal_file_);
|
size_t bytes_read = fread(buffer, sizeof(char), length, internal_file_);
|
||||||
|
VLOG(2) << "Read " << length << " return " << bytes_read << " error "
|
||||||
|
<< ferror(internal_file_);
|
||||||
|
if (bytes_read == 0 && ferror(internal_file_) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t LocalFile::Write(const void* buffer, uint64_t length) {
|
int64_t LocalFile::Write(const void* buffer, uint64_t length) {
|
||||||
DCHECK(buffer != NULL);
|
DCHECK(buffer != NULL);
|
||||||
DCHECK(internal_file_ != NULL);
|
DCHECK(internal_file_ != NULL);
|
||||||
return fwrite(buffer, sizeof(char), length, internal_file_);
|
size_t bytes_written = fwrite(buffer, sizeof(char), length, internal_file_);
|
||||||
|
VLOG(2) << "Write " << length << " return " << bytes_written << " error "
|
||||||
|
<< ferror(internal_file_);
|
||||||
|
if (bytes_written == 0 && ferror(internal_file_) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t LocalFile::Size() {
|
int64_t LocalFile::Size() {
|
||||||
|
|
|
@ -58,13 +58,14 @@ bool ThreadedIoFile::Open() {
|
||||||
bool ThreadedIoFile::Close() {
|
bool ThreadedIoFile::Close() {
|
||||||
DCHECK(internal_file_);
|
DCHECK(internal_file_);
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
if (mode_ == kOutputMode)
|
if (mode_ == kOutputMode)
|
||||||
Flush();
|
result = Flush();
|
||||||
|
|
||||||
cache_.Close();
|
cache_.Close();
|
||||||
task_exit_event_.Wait();
|
task_exit_event_.Wait();
|
||||||
|
|
||||||
bool result = internal_file_.release()->Close();
|
result &= internal_file_.release()->Close();
|
||||||
delete this;
|
delete this;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -110,6 +111,9 @@ bool ThreadedIoFile::Flush() {
|
||||||
DCHECK(internal_file_);
|
DCHECK(internal_file_);
|
||||||
DCHECK_EQ(kOutputMode, mode_);
|
DCHECK_EQ(kOutputMode, mode_);
|
||||||
|
|
||||||
|
if (NoBarrier_Load(&internal_file_error_))
|
||||||
|
return false;
|
||||||
|
|
||||||
flushing_ = true;
|
flushing_ = true;
|
||||||
cache_.Close();
|
cache_.Close();
|
||||||
flush_complete_event_.Wait();
|
flush_complete_event_.Wait();
|
||||||
|
@ -204,6 +208,10 @@ void ThreadedIoFile::RunInOutputMode() {
|
||||||
if (write_result < 0) {
|
if (write_result < 0) {
|
||||||
NoBarrier_Store(&internal_file_error_, write_result);
|
NoBarrier_Store(&internal_file_error_, write_result);
|
||||||
cache_.Close();
|
cache_.Close();
|
||||||
|
if (flushing_) {
|
||||||
|
flushing_ = false;
|
||||||
|
flush_complete_event_.Signal();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bytes_written += write_result;
|
bytes_written += write_result;
|
||||||
|
|
|
@ -90,8 +90,10 @@ Status SingleSegmentSegmenter::DoFinalize() {
|
||||||
|
|
||||||
// Close the temp file to prepare for reading later.
|
// Close the temp file to prepare for reading later.
|
||||||
if (!temp_file_.release()->Close()) {
|
if (!temp_file_.release()->Close()) {
|
||||||
return Status(error::FILE_FAILURE,
|
return Status(
|
||||||
"Cannot close the temp file " + temp_file_name_);
|
error::FILE_FAILURE,
|
||||||
|
"Cannot close the temp file " + temp_file_name_ +
|
||||||
|
", possibly file permission issue or running out of disk space.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<File, FileCloser> file(
|
std::unique_ptr<File, FileCloser> file(
|
||||||
|
@ -142,6 +144,16 @@ Status SingleSegmentSegmenter::DoFinalize() {
|
||||||
UpdateProgress(static_cast<double>(size) / temp_file->Size() *
|
UpdateProgress(static_cast<double>(size) / temp_file->Size() *
|
||||||
re_segment_progress_target);
|
re_segment_progress_target);
|
||||||
}
|
}
|
||||||
|
if (!temp_file.release()->Close()) {
|
||||||
|
return Status(error::FILE_FAILURE, "Cannot close the temp file " +
|
||||||
|
temp_file_name_ + " after reading.");
|
||||||
|
}
|
||||||
|
if (!file.release()->Close()) {
|
||||||
|
return Status(
|
||||||
|
error::FILE_FAILURE,
|
||||||
|
"Cannot close file " + options().output_file_name +
|
||||||
|
", possibly file permission issue or running out of disk space.");
|
||||||
|
}
|
||||||
SetComplete();
|
SetComplete();
|
||||||
return Status::OK;
|
return Status::OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,10 @@ Status MkvWriter::Open(const std::string& name) {
|
||||||
Status MkvWriter::Close() {
|
Status MkvWriter::Close() {
|
||||||
const std::string file_name = file_->file_name();
|
const std::string file_name = file_->file_name();
|
||||||
if (!file_.release()->Close()) {
|
if (!file_.release()->Close()) {
|
||||||
return Status(error::FILE_FAILURE, "Cannot close file " + file_name);
|
return Status(
|
||||||
|
error::FILE_FAILURE,
|
||||||
|
"Cannot close file " + file_name +
|
||||||
|
", possibly file permission issue or running out of disk space.");
|
||||||
}
|
}
|
||||||
return Status::OK;
|
return Status::OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue