aboutsummaryrefslogtreecommitdiffstats
path: root/src/command
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-02-26 08:39:44 +0100
committerMax Kellermann <max@duempel.org>2014-02-27 20:49:13 +0100
commite9a85aa4e4d0634548b5c97461beb27ae5559338 (patch)
tree7cdfdd0ae0d990a8adbecc34f32d073627483205 /src/command
parent2a16fc74fd354484a70efcc5b6dbfcdd73ee5f5a (diff)
downloadmpd-e9a85aa4e4d0634548b5c97461beb27ae5559338.tar.gz
mpd-e9a85aa4e4d0634548b5c97461beb27ae5559338.tar.xz
mpd-e9a85aa4e4d0634548b5c97461beb27ae5559338.zip
db/simple: mount points
A SimpleDatabase instance can now "mount" other Database instances at certain locations. This is used to use a new SimpleDatabase instance for each storage mount (issued with the "mount" protocol command). Each such instance has its own database file, stored in the directory that is specified with the "cache_directory" option.
Diffstat (limited to '')
-rw-r--r--src/command/CommandError.cxx4
-rw-r--r--src/command/StorageCommands.cxx47
2 files changed, 51 insertions, 0 deletions
diff --git a/src/command/CommandError.cxx b/src/command/CommandError.cxx
index c94ffea63..89085fc68 100644
--- a/src/command/CommandError.cxx
+++ b/src/command/CommandError.cxx
@@ -112,6 +112,10 @@ print_error(Client &client, const Error &error)
case DB_NOT_FOUND:
command_error(client, ACK_ERROR_NO_EXIST, "Not found");
return CommandResult::ERROR;
+
+ case DB_CONFLICT:
+ command_error(client, ACK_ERROR_ARG, "Conflict");
+ return CommandResult::ERROR;
}
#endif
} else if (error.IsDomain(errno_domain)) {
diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx
index 92d235f4c..f0698f04b 100644
--- a/src/command/StorageCommands.cxx
+++ b/src/command/StorageCommands.cxx
@@ -29,6 +29,8 @@
#include "Instance.hxx"
#include "storage/Registry.hxx"
#include "storage/CompositeStorage.hxx"
+#include "db/plugins/simple/SimpleDatabasePlugin.hxx"
+#include "db/update/Service.hxx"
#include "Idle.hxx"
static void
@@ -98,6 +100,16 @@ handle_mount(Client &client, gcc_unused int argc, char *argv[])
return CommandResult::ERROR;
}
+ if (strchr(local_uri, '/') != nullptr) {
+ /* allow only top-level mounts for now */
+ /* TODO: eliminate this limitation after ensuring that
+ UpdateQueue::Erase() really gets called for every
+ unmount, and no Directory disappears recursively
+ during database update */
+ command_error(client, ACK_ERROR_ARG, "Bad mount point");
+ return CommandResult::ERROR;
+ }
+
Error error;
Storage *storage = CreateStorageURI(remote_uri, error);
if (storage == nullptr) {
@@ -111,6 +123,23 @@ handle_mount(Client &client, gcc_unused int argc, char *argv[])
composite.Mount(local_uri, storage);
idle_add(IDLE_MOUNT);
+
+#ifdef ENABLE_DATABASE
+ Database *_db = client.partition.instance.database;
+ if (_db != nullptr && _db->IsPlugin(simple_db_plugin)) {
+ SimpleDatabase &db = *(SimpleDatabase *)_db;
+
+ if (!db.Mount(local_uri, remote_uri, error)) {
+ composite.Unmount(local_uri);
+ return print_error(client, error);
+ }
+
+ // TODO: call Instance::OnDatabaseModified()?
+ // TODO: trigger database update?
+ idle_add(IDLE_DATABASE);
+ }
+#endif
+
return CommandResult::OK;
}
@@ -132,11 +161,29 @@ handle_unmount(Client &client, gcc_unused int argc, char *argv[])
return CommandResult::ERROR;
}
+#ifdef ENABLE_DATABASE
+ if (client.partition.instance.update != nullptr)
+ /* ensure that no database update will attempt to work
+ with the database/storage instances we're about to
+ destroy here */
+ client.partition.instance.update->CancelMount(local_uri);
+
+ Database *_db = client.partition.instance.database;
+ if (_db != nullptr && _db->IsPlugin(simple_db_plugin)) {
+ SimpleDatabase &db = *(SimpleDatabase *)_db;
+
+ if (db.Unmount(local_uri))
+ // TODO: call Instance::OnDatabaseModified()?
+ idle_add(IDLE_DATABASE);
+ }
+#endif
+
if (!composite.Unmount(local_uri)) {
command_error(client, ACK_ERROR_ARG, "Not a mount point");
return CommandResult::ERROR;
}
idle_add(IDLE_MOUNT);
+
return CommandResult::OK;
}