diff --git a/NEWS b/NEWS index a582225f5..2672c84d5 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ ver 0.19 (not yet released) - proxy: forward "idle" events - proxy: forward the "update" command - proxy: copy "Last-Modified" from remote directories + - simple: compress the database file using gzip - upnp: new plugin - cancel the update on shutdown * storage diff --git a/doc/user.xml b/doc/user.xml index 1b399c2f4..d70c9ead1 100644 --- a/doc/user.xml +++ b/doc/user.xml @@ -925,6 +925,18 @@ systemctl start mpd.socket The path of the database file. + + + + compress + yes|no + + + Compress the database file using + gzip? Enabled by default (if + built with zlib). + + diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx index 9e750996c..3048194cd 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx @@ -34,6 +34,7 @@ #include "fs/io/TextFile.hxx" #include "fs/io/BufferedOutputStream.hxx" #include "fs/io/FileOutputStream.hxx" +#include "fs/io/GzipOutputStream.hxx" #include "config/ConfigData.hxx" #include "fs/FileSystem.hxx" #include "util/CharUtil.hxx" @@ -48,13 +49,23 @@ static constexpr Domain simple_db_domain("simple_db"); inline SimpleDatabase::SimpleDatabase() :Database(simple_db_plugin), path(AllocatedPath::Null()), +#ifdef HAVE_ZLIB + compress(true), +#endif cache_path(AllocatedPath::Null()), prefixed_light_song(nullptr) {} -inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path) +inline SimpleDatabase::SimpleDatabase(AllocatedPath &&_path, +#ifndef HAVE_ZLIB + gcc_unused +#endif + bool _compress) :Database(simple_db_plugin), path(std::move(_path)), path_utf8(path.ToUTF8()), +#ifdef HAVE_ZLIB + compress(_compress), +#endif cache_path(AllocatedPath::Null()), prefixed_light_song(nullptr) { } @@ -90,6 +101,10 @@ SimpleDatabase::Configure(const config_param ¶m, Error &error) if (path.IsNull() && error.IsDefined()) return false; +#ifdef HAVE_ZLIB + compress = param.GetBlockValue("compress", compress); +#endif + return true; } @@ -369,11 +384,42 @@ SimpleDatabase::Save(Error &error) if (!fos.IsDefined()) return false; - BufferedOutputStream bos(fos); + OutputStream *os = &fos; + +#ifdef HAVE_ZLIB + GzipOutputStream *gzip = nullptr; + if (compress) { + gzip = new GzipOutputStream(*os, error); + if (!gzip->IsDefined()) { + delete gzip; + return false; + } + + os = gzip; + } +#endif + + BufferedOutputStream bos(*os); db_save_internal(bos, *root); - if (!bos.Flush(error) || !fos.Commit(error)) + if (!bos.Flush(error)) { +#ifdef HAVE_ZLIB + delete gzip; +#endif + return false; + } + +#ifdef HAVE_ZLIB + if (gzip != nullptr) { + bool success = gzip->Flush(error); + delete gzip; + if (!success) + return false; + } +#endif + + if (!fos.Commit(error)) return false; struct stat st; @@ -435,8 +481,12 @@ SimpleDatabase::Mount(const char *local_uri, const char *storage_uri, std::string name(storage_uri); std::replace_if(name.begin(), name.end(), IsUnsafeChar, '_'); +#ifndef HAVE_ZLIB + constexpr bool compress = false; +#endif auto db = new SimpleDatabase(AllocatedPath::Build(cache_path, - name.c_str())); + name.c_str()), + compress); if (!db->Open(error)) { delete db; return false; diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.hxx b/src/db/plugins/simple/SimpleDatabasePlugin.hxx index e27b3d956..7ba71e272 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.hxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.hxx @@ -20,6 +20,7 @@ #ifndef MPD_SIMPLE_DATABASE_PLUGIN_HXX #define MPD_SIMPLE_DATABASE_PLUGIN_HXX +#include "check.h" #include "db/Interface.hxx" #include "fs/AllocatedPath.hxx" #include "db/LightSong.hxx" @@ -38,6 +39,10 @@ class SimpleDatabase : public Database { AllocatedPath path; std::string path_utf8; +#ifdef HAVE_ZLIB + bool compress; +#endif + /** * The path where cache files for Mount() are located. */ @@ -64,7 +69,7 @@ class SimpleDatabase : public Database { SimpleDatabase(); - SimpleDatabase(AllocatedPath &&_path); + SimpleDatabase(AllocatedPath &&_path, bool _compress); public: static Database *Create(EventLoop &loop, DatabaseListener &listener,