diff options
author | Max Kellermann <max@duempel.org> | 2015-12-16 10:24:43 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2015-12-16 10:24:43 +0100 |
commit | e4a06da14e1184eacd00834aaf05c5457703a7eb (patch) | |
tree | 7d4d168bfd8475e9113b2d9d2e4b8b74c606f092 /src | |
parent | 36d6ead65cf507948744ee5d8615c8ef20e42f9d (diff) |
fs/io/OutputStream: use C++ exceptions in Write()
Diffstat (limited to 'src')
-rw-r--r-- | src/PlaylistFile.cxx | 7 | ||||
-rw-r--r-- | src/PlaylistSave.cxx | 4 | ||||
-rw-r--r-- | src/StateFile.cxx | 13 | ||||
-rw-r--r-- | src/StateFile.hxx | 2 | ||||
-rw-r--r-- | src/db/plugins/simple/DirectorySave.cxx | 3 | ||||
-rw-r--r-- | src/db/plugins/simple/SimpleDatabasePlugin.cxx | 14 | ||||
-rw-r--r-- | src/db/plugins/simple/SimpleDatabasePlugin.hxx | 2 | ||||
-rw-r--r-- | src/db/update/Service.cxx | 4 | ||||
-rw-r--r-- | src/encoder/ToOutputStream.cxx | 9 | ||||
-rw-r--r-- | src/encoder/ToOutputStream.hxx | 5 | ||||
-rw-r--r-- | src/fs/io/BufferedOutputStream.cxx | 63 | ||||
-rw-r--r-- | src/fs/io/BufferedOutputStream.hxx | 40 | ||||
-rw-r--r-- | src/fs/io/FileOutputStream.cxx | 45 | ||||
-rw-r--r-- | src/fs/io/FileOutputStream.hxx | 2 | ||||
-rw-r--r-- | src/fs/io/GzipOutputStream.cxx | 37 | ||||
-rw-r--r-- | src/fs/io/GzipOutputStream.hxx | 6 | ||||
-rw-r--r-- | src/fs/io/OutputStream.hxx | 8 | ||||
-rw-r--r-- | src/fs/io/StdioOutputStream.hxx | 5 | ||||
-rw-r--r-- | src/output/plugins/RecorderOutputPlugin.cxx | 60 |
19 files changed, 122 insertions, 207 deletions
diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index c90af9760..d0af1c7f5 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -239,8 +239,7 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path, for (const auto &uri_utf8 : contents) playlist_print_uri(bos, uri_utf8.c_str()); - if (!bos.Flush(error)) - return false; + bos.Flush(); fos.Commit(); return true; @@ -415,9 +414,7 @@ spl_append_song(const char *utf8path, const DetachedSong &song, Error &error) playlist_print_song(bos, song); - if (!bos.Flush(error)) - return false; - + bos.Flush(); fos.Commit(); idle_add(IDLE_STORED_PLAYLIST); diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx index d83ceb2b7..9ed4d832b 100644 --- a/src/PlaylistSave.cxx +++ b/src/PlaylistSave.cxx @@ -86,9 +86,7 @@ spl_save_queue(const char *name_utf8, const Queue &queue, Error &error) for (unsigned i = 0; i < queue.GetLength(); i++) playlist_print_song(bos, queue.Get(i)); - if (!bos.Flush(error)) - return false; - + bos.Flush(); fos.Commit(); idle_add(IDLE_STORED_PLAYLIST); diff --git a/src/StateFile.cxx b/src/StateFile.cxx index 7c92ae0ee..fb031d04b 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -75,12 +75,12 @@ StateFile::Write(BufferedOutputStream &os) playlist_state_save(os, partition.playlist, partition.pc); } -inline bool -StateFile::Write(OutputStream &os, Error &error) +inline void +StateFile::Write(OutputStream &os) { BufferedOutputStream bos(os); Write(bos); - return bos.Flush(error); + bos.Flush(); } void @@ -90,13 +90,8 @@ StateFile::Write() "Saving state file %s", path_utf8.c_str()); try { - Error error; FileOutputStream fos(path); - if (!Write(fos, error)) { - LogError(error); - return; - } - + Write(fos); fos.Commit(); } catch (const std::exception &e) { LogError(e); diff --git a/src/StateFile.hxx b/src/StateFile.hxx index b96b89dfb..4157552fd 100644 --- a/src/StateFile.hxx +++ b/src/StateFile.hxx @@ -60,7 +60,7 @@ public: void CheckModified(); private: - bool Write(OutputStream &os, Error &error); + void Write(OutputStream &os); void Write(BufferedOutputStream &os); /** diff --git a/src/db/plugins/simple/DirectorySave.cxx b/src/db/plugins/simple/DirectorySave.cxx index 868507c67..017854c6d 100644 --- a/src/db/plugins/simple/DirectorySave.cxx +++ b/src/db/plugins/simple/DirectorySave.cxx @@ -90,9 +90,6 @@ directory_save(BufferedOutputStream &os, const Directory &directory) if (!child.IsMount()) directory_save(os, child); - - if (!os.Check()) - return; } for (const auto &song : directory.songs) diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx index aa62870c6..113e9b321 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx @@ -364,8 +364,8 @@ SimpleDatabase::GetStats(const DatabaseSelection &selection, return ::GetStats(*this, selection, stats, error); } -bool -SimpleDatabase::Save(Error &error) +void +SimpleDatabase::Save() { { const ScopeDatabaseLock protect; @@ -395,16 +395,12 @@ SimpleDatabase::Save(Error &error) db_save_internal(bos, *root); - if (!bos.Flush(error)) { - return false; - } + bos.Flush(); #ifdef ENABLE_ZLIB if (gzip != nullptr) { - bool success = gzip->Flush(error); + gzip->Flush(); gzip.reset(); - if (!success) - return false; } #endif @@ -413,8 +409,6 @@ SimpleDatabase::Save(Error &error) FileInfo fi; if (GetFileInfo(path, fi)) mtime = fi.GetModificationTime(); - - return true; } bool diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.hxx b/src/db/plugins/simple/SimpleDatabasePlugin.hxx index 7a28099d9..438bd1280 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.hxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.hxx @@ -83,7 +83,7 @@ public: return *root; } - bool Save(Error &error); + void Save(); /** * Returns true if there is a valid database file on the disk. diff --git a/src/db/update/Service.cxx b/src/db/update/Service.cxx index f1dc581d8..9d02ee60d 100644 --- a/src/db/update/Service.cxx +++ b/src/db/update/Service.cxx @@ -130,9 +130,7 @@ UpdateService::Task() if (modified || !next.db->FileExists()) { try { - Error error; - if (!next.db->Save(error)) - LogError(error, "Failed to save database"); + next.db->Save(); } catch (const std::exception &e) { LogError(e, "Failed to save database"); } diff --git a/src/encoder/ToOutputStream.cxx b/src/encoder/ToOutputStream.cxx index 43345cf70..0d2cfc96c 100644 --- a/src/encoder/ToOutputStream.cxx +++ b/src/encoder/ToOutputStream.cxx @@ -22,8 +22,8 @@ #include "EncoderInterface.hxx" #include "fs/io/OutputStream.hxx" -bool -EncoderToOutputStream(OutputStream &os, Encoder &encoder, Error &error) +void +EncoderToOutputStream(OutputStream &os, Encoder &encoder) { while (true) { /* read from the encoder */ @@ -31,11 +31,10 @@ EncoderToOutputStream(OutputStream &os, Encoder &encoder, Error &error) char buffer[32768]; size_t nbytes = encoder_read(&encoder, buffer, sizeof(buffer)); if (nbytes == 0) - return true; + return; /* write everything to the stream */ - if (!os.Write(buffer, nbytes, error)) - return false; + os.Write(buffer, nbytes); } } diff --git a/src/encoder/ToOutputStream.hxx b/src/encoder/ToOutputStream.hxx index e3fb7b908..d87295d89 100644 --- a/src/encoder/ToOutputStream.hxx +++ b/src/encoder/ToOutputStream.hxx @@ -24,9 +24,8 @@ struct Encoder; class OutputStream; -class Error; -bool -EncoderToOutputStream(OutputStream &os, Encoder &encoder, Error &error); +void +EncoderToOutputStream(OutputStream &os, Encoder &encoder); #endif diff --git a/src/fs/io/BufferedOutputStream.cxx b/src/fs/io/BufferedOutputStream.cxx index 2268eb50c..ec727ae19 100644 --- a/src/fs/io/BufferedOutputStream.cxx +++ b/src/fs/io/BufferedOutputStream.cxx @@ -26,7 +26,7 @@ #include <stdio.h> bool -BufferedOutputStream::AppendToBuffer(const void *data, size_t size) +BufferedOutputStream::AppendToBuffer(const void *data, size_t size) noexcept { auto r = buffer.Write(); if (r.size < size) @@ -37,46 +37,36 @@ BufferedOutputStream::AppendToBuffer(const void *data, size_t size) return true; } -bool +void BufferedOutputStream::Write(const void *data, size_t size) { - if (gcc_unlikely(last_error.IsDefined())) - /* the stream has already failed */ - return false; - /* try to append to the current buffer */ if (AppendToBuffer(data, size)) - return true; + return; /* not enough room in the buffer - flush it */ - if (!Flush()) - return false; + Flush(); /* see if there's now enough room */ if (AppendToBuffer(data, size)) - return true; + return; /* too large for the buffer: direct write */ - return os.Write(data, size, last_error); + os.Write(data, size); } -bool +void BufferedOutputStream::Write(const char *p) { - return Write(p, strlen(p)); + Write(p, strlen(p)); } -bool +void BufferedOutputStream::Format(const char *fmt, ...) { - if (gcc_unlikely(last_error.IsDefined())) - return false; - auto r = buffer.Write(); if (r.IsEmpty()) { - if (!Flush()) - return false; - + Flush(); r = buffer.Write(); } @@ -90,8 +80,7 @@ BufferedOutputStream::Format(const char *fmt, ...) /* buffer was not large enough; flush it and try again */ - if (!Flush()) - return false; + Flush(); r = buffer.Write(); @@ -112,37 +101,15 @@ BufferedOutputStream::Format(const char *fmt, ...) } buffer.Append(size); - return true; } -bool +void BufferedOutputStream::Flush() { - if (!Check()) - return false; - - auto r = buffer.Read(); - if (r.IsEmpty()) - return true; - - bool success = os.Write(r.data, r.size, last_error); - if (gcc_likely(success)) - buffer.Consume(r.size); - return success; -} - -bool -BufferedOutputStream::Flush(Error &error) -{ - if (!Check(error)) - return false; - auto r = buffer.Read(); if (r.IsEmpty()) - return true; + return; - bool success = os.Write(r.data, r.size, error); - if (gcc_likely(success)) - buffer.Consume(r.size); - return success; + os.Write(r.data, r.size); + buffer.Consume(r.size); } diff --git a/src/fs/io/BufferedOutputStream.hxx b/src/fs/io/BufferedOutputStream.hxx index 63a3f4aee..9e4a18a52 100644 --- a/src/fs/io/BufferedOutputStream.hxx +++ b/src/fs/io/BufferedOutputStream.hxx @@ -23,67 +23,37 @@ #include "check.h" #include "Compiler.h" #include "util/DynamicFifoBuffer.hxx" -#include "util/Error.hxx" #include <stddef.h> class OutputStream; -class Error; /** * An #OutputStream wrapper that buffers its output to reduce the * number of OutputStream::Write() calls. - * - * It simplifies error handling by managing an #Error attribute. - * Invoke any number of writes, and check for errors in the end using - * Check(). */ class BufferedOutputStream { OutputStream &os; DynamicFifoBuffer<char> buffer; - Error last_error; - public: BufferedOutputStream(OutputStream &_os) :os(_os), buffer(32768) {} - bool Write(const void *data, size_t size); - bool Write(const char *p); + void Write(const void *data, size_t size); + void Write(const char *p); gcc_printf(2,3) - bool Format(const char *fmt, ...); - - /** - * Returns false if an error has occurred. - */ - gcc_pure - bool Check() const { - return !last_error.IsDefined(); - } - - /** - * Returns false if an error has occurred. In that case, a - * copy of the #Error is returned. - */ - bool Check(Error &error) const { - if (last_error.IsDefined()) { - error.Set(last_error); - return false; - } else - return true; - } + void Format(const char *fmt, ...); /** * Write buffer contents to the #OutputStream. */ - bool Flush(); - - bool Flush(Error &error); + void Flush(); private: - bool AppendToBuffer(const void *data, size_t size); + bool AppendToBuffer(const void *data, size_t size) noexcept; }; #endif diff --git a/src/fs/io/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx index d0b1edd56..8eabaa313 100644 --- a/src/fs/io/FileOutputStream.cxx +++ b/src/fs/io/FileOutputStream.cxx @@ -21,9 +21,6 @@ #include "FileOutputStream.hxx" #include "fs/FileSystem.hxx" #include "system/Error.hxx" -#include "util/Error.hxx" - -#include <system_error> #ifdef WIN32 @@ -50,26 +47,19 @@ BaseFileOutputStream::Tell() const return uint64_t(high) << 32 | uint64_t(low); } -bool -BaseFileOutputStream::Write(const void *data, size_t size, Error &error) +void +BaseFileOutputStream::Write(const void *data, size_t size) { assert(IsDefined()); DWORD nbytes; - if (!WriteFile(handle, data, size, &nbytes, nullptr)) { - error.FormatLastError("Failed to write to %s", - path.ToUTF8().c_str()); - return false; - } - - if (size_t(nbytes) != size) { - error.FormatLastError(ERROR_DISK_FULL, - "Failed to write to %s", - path.ToUTF8().c_str()); - return false; - } + if (!WriteFile(handle, data, size, &nbytes, nullptr)) + throw FormatLastError("Failed to write to %s", + GetPath().c_str()); - return true; + if (size_t(nbytes) != size) + throw FormatLastError(ERROR_DISK_FULL, "Failed to write to %s", + GetPath().c_str()); } void @@ -143,22 +133,17 @@ BaseFileOutputStream::Tell() const return fd.Tell(); } -bool -BaseFileOutputStream::Write(const void *data, size_t size, Error &error) +void +BaseFileOutputStream::Write(const void *data, size_t size) { assert(IsDefined()); ssize_t nbytes = fd.Write(data, size); - if (nbytes < 0) { - error.FormatErrno("Failed to write to %s", GetPath().c_str()); - return false; - } else if ((size_t)nbytes < size) { - error.FormatErrno(ENOSPC, - "Failed to write to %s", GetPath().c_str()); - return false; - } - - return true; + if (nbytes < 0) + throw FormatErrno("Failed to write to %s", GetPath().c_str()); + else if ((size_t)nbytes < size) + throw FormatErrno(ENOSPC, "Failed to write to %s", + GetPath().c_str()); } void diff --git a/src/fs/io/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx index 0cf8bfc4d..00bd77d9f 100644 --- a/src/fs/io/FileOutputStream.hxx +++ b/src/fs/io/FileOutputStream.hxx @@ -119,7 +119,7 @@ public: uint64_t Tell() const; /* virtual methods from class OutputStream */ - bool Write(const void *data, size_t size, Error &error) override; + void Write(const void *data, size_t size) override; }; class FileOutputStream final : public BaseFileOutputStream { diff --git a/src/fs/io/GzipOutputStream.cxx b/src/fs/io/GzipOutputStream.cxx index e903aaaa3..a4cccf298 100644 --- a/src/fs/io/GzipOutputStream.cxx +++ b/src/fs/io/GzipOutputStream.cxx @@ -21,7 +21,6 @@ #include "GzipOutputStream.hxx" #include "lib/zlib/Domain.hxx" #include "lib/zlib/Error.hxx" -#include "util/Error.hxx" GzipOutputStream::GzipOutputStream(OutputStream &_next) throw(ZlibError) :next(_next) @@ -47,8 +46,8 @@ GzipOutputStream::~GzipOutputStream() deflateEnd(&z); } -bool -GzipOutputStream::Flush(Error &error) +void +GzipOutputStream::Flush() { /* no more input */ z.next_in = nullptr; @@ -60,21 +59,18 @@ GzipOutputStream::Flush(Error &error) z.avail_out = sizeof(output); int result = deflate(&z, Z_FINISH); - if (z.next_out > output && - !next.Write(output, z.next_out - output, error)) - return false; + if (z.next_out > output) + next.Write(output, z.next_out - output); if (result == Z_STREAM_END) - return true; - else if (result != Z_OK) { - error.Set(zlib_domain, result, zError(result)); - return false; - } - } + break; + else if (result != Z_OK) + throw ZlibError(result); + } } -bool -GzipOutputStream::Write(const void *_data, size_t size, Error &error) +void +GzipOutputStream::Write(const void *_data, size_t size) { /* zlib's API requires non-const input pointer */ void *data = const_cast<void *>(_data); @@ -88,15 +84,10 @@ GzipOutputStream::Write(const void *_data, size_t size, Error &error) z.avail_out = sizeof(output); int result = deflate(&z, Z_NO_FLUSH); - if (result != Z_OK) { - error.Set(zlib_domain, result, zError(result)); - return false; - } + if (result != Z_OK) + throw ZlibError(result); - if (z.next_out > output && - !next.Write(output, z.next_out - output, error)) - return false; + if (z.next_out > output) + next.Write(output, z.next_out - output); } - - return true; } diff --git a/src/fs/io/GzipOutputStream.hxx b/src/fs/io/GzipOutputStream.hxx index 700a69354..dbf509ecc 100644 --- a/src/fs/io/GzipOutputStream.hxx +++ b/src/fs/io/GzipOutputStream.hxx @@ -28,8 +28,6 @@ #include <assert.h> #include <zlib.h> -class Error; - /** * A filter that compresses data written to it using zlib, forwarding * compressed data in the "gzip" format. @@ -52,10 +50,10 @@ public: * Finish the file and write all data remaining in zlib's * output buffer. */ - bool Flush(Error &error); + void Flush(); /* virtual methods from class OutputStream */ - bool Write(const void *data, size_t size, Error &error) override; + void Write(const void *data, size_t size) override; }; #endif diff --git a/src/fs/io/OutputStream.hxx b/src/fs/io/OutputStream.hxx index f7d101180..f2eda1ecd 100644 --- a/src/fs/io/OutputStream.hxx +++ b/src/fs/io/OutputStream.hxx @@ -21,18 +21,18 @@ #define MPD_OUTPUT_STREAM_HXX #include "check.h" -#include "Compiler.h" #include <stddef.h> -class Error; - class OutputStream { public: OutputStream() = default; OutputStream(const OutputStream &) = delete; - virtual bool Write(const void *data, size_t size, Error &error) = 0; + /** + * Throws std::exception on error. + */ + virtual void Write(const void *data, size_t size) = 0; }; #endif diff --git a/src/fs/io/StdioOutputStream.hxx b/src/fs/io/StdioOutputStream.hxx index 88dbe6f00..99a32a052 100644 --- a/src/fs/io/StdioOutputStream.hxx +++ b/src/fs/io/StdioOutputStream.hxx @@ -22,7 +22,6 @@ #include "check.h" #include "OutputStream.hxx" -#include "fs/AllocatedPath.hxx" #include "Compiler.h" #include <stdio.h> @@ -34,12 +33,10 @@ public: StdioOutputStream(FILE *_file):file(_file) {} /* virtual methods from class OutputStream */ - bool Write(const void *data, size_t size, - gcc_unused Error &error) override { + void Write(const void *data, size_t size) override { fwrite(data, 1, size, file); /* this class is debug-only and ignores errors */ - return true; } }; diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx index 562e36f87..cab303641 100644 --- a/src/output/plugins/RecorderOutputPlugin.cxx +++ b/src/output/plugins/RecorderOutputPlugin.cxx @@ -95,7 +95,7 @@ class RecorderOutput { /** * Writes pending data from the encoder to the output file. */ - bool EncoderToFile(Error &error); + void EncoderToFile(); void SendTag(const Tag &tag); @@ -175,12 +175,12 @@ RecorderOutput::Create(const ConfigBlock &block, Error &error) return recorder; } -inline bool -RecorderOutput::EncoderToFile(Error &error) +inline void +RecorderOutput::EncoderToFile() { assert(file != nullptr); - return EncoderToOutputStream(*file, *encoder, error); + EncoderToOutputStream(*file, *encoder); } inline bool @@ -213,9 +213,11 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error) } if (!HasDynamicPath()) { - if (!EncoderToFile(error)) { + try { + EncoderToFile(); + } catch (const std::exception &e) { encoder->Close(); - delete file; + error.Set(recorder_domain, e.what()); return false; } } else { @@ -237,8 +239,15 @@ RecorderOutput::Commit(Error &error) /* flush the encoder and write the rest to the file */ - bool success = encoder_end(encoder, error) && - EncoderToFile(error); + bool success = encoder_end(encoder, error); + if (success) { + try { + EncoderToFile(); + } catch (...) { + encoder->Close(); + throw; + } + } /* now really close everything */ @@ -328,9 +337,12 @@ RecorderOutput::ReopenFormat(AllocatedPath &&new_path, Error &error) AudioFormat as before */ assert(new_audio_format == effective_audio_format); - if (!EncoderToOutputStream(*new_file, *encoder, error)) { + try { + EncoderToOutputStream(*new_file, *encoder); + } catch (const std::exception &e) { encoder->Close(); delete new_file; + error.Set(recorder_domain, e.what()); return false; } @@ -376,9 +388,19 @@ RecorderOutput::SendTag(const Tag &tag) } Error error; - if (!encoder_pre_tag(encoder, error) || - !EncoderToFile(error) || - !encoder_tag(encoder, tag, error)) + if (!encoder_pre_tag(encoder, error)) { + LogError(error); + return; + } + + try { + EncoderToFile(); + } catch (const std::exception &e) { + LogError(e); + return; + } + + if (!encoder_tag(encoder, tag, error)) LogError(error); } @@ -393,9 +415,17 @@ RecorderOutput::Play(const void *chunk, size_t size, Error &error) return size; } - return encoder_write(encoder, chunk, size, error) && - EncoderToFile(error) - ? size : 0; + if (!encoder_write(encoder, chunk, size, error)) + return 0; + + try { + EncoderToFile(); + } catch (const std::exception &e) { + error.Set(recorder_domain, e.what()); + return 0; + } + + return size; } typedef AudioOutputWrapper<RecorderOutput> Wrapper; |