Commit 0935ae33 authored by Max Kellermann's avatar Max Kellermann

StorageCommands: add command "listmounts"

parent 9e02b13a
...@@ -107,6 +107,7 @@ static const struct command commands[] = { ...@@ -107,6 +107,7 @@ static const struct command commands[] = {
{ "list", PERMISSION_READ, 1, -1, handle_list }, { "list", PERMISSION_READ, 1, -1, handle_list },
{ "listall", PERMISSION_READ, 0, 1, handle_listall }, { "listall", PERMISSION_READ, 0, 1, handle_listall },
{ "listallinfo", PERMISSION_READ, 0, 1, handle_listallinfo }, { "listallinfo", PERMISSION_READ, 0, 1, handle_listallinfo },
{ "listmounts", PERMISSION_READ, 0, 0, handle_listmounts },
#endif #endif
#ifdef ENABLE_NEIGHBOR_PLUGINS #ifdef ENABLE_NEIGHBOR_PLUGINS
{ "listneighbors", PERMISSION_READ, 0, 0, handle_listneighbors }, { "listneighbors", PERMISSION_READ, 0, 0, handle_listneighbors },
......
...@@ -21,13 +21,63 @@ ...@@ -21,13 +21,63 @@
#include "StorageCommands.hxx" #include "StorageCommands.hxx"
#include "CommandError.hxx" #include "CommandError.hxx"
#include "protocol/Result.hxx" #include "protocol/Result.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include "fs/Traits.hxx"
#include "client/Client.hxx" #include "client/Client.hxx"
#include "Partition.hxx" #include "Partition.hxx"
#include "Instance.hxx" #include "Instance.hxx"
#include "storage/Registry.hxx" #include "storage/Registry.hxx"
#include "storage/CompositeStorage.hxx" #include "storage/CompositeStorage.hxx"
static void
print_storage_uri(Client &client, const Storage &storage)
{
std::string uri = storage.MapUTF8("");
if (uri.empty())
return;
if (PathTraitsFS::IsAbsolute(uri.c_str())) {
/* storage points to local directory */
if (!client.IsLocal())
/* only "local" clients may see local paths
(same policy as with the "config"
command) */
return;
} else {
/* hide username/passwords from client */
std::string allocated = uri_remove_auth(uri.c_str());
if (!allocated.empty())
uri = std::move(allocated);
}
client_printf(client, "storage: %s\n", uri.c_str());
}
CommandResult
handle_listmounts(Client &client, gcc_unused int argc, gcc_unused char *argv[])
{
Storage *_composite = client.partition.instance.storage;
if (_composite == nullptr) {
command_error(client, ACK_ERROR_NO_EXIST, "No database");
return CommandResult::ERROR;
}
CompositeStorage &composite = *(CompositeStorage *)_composite;
const auto visitor = [&client](const char *mount_uri,
const Storage &storage){
client_printf(client, "mount: %s\n", mount_uri);
print_storage_uri(client, storage);
};
composite.VisitMounts(visitor);
return CommandResult::OK;
}
CommandResult CommandResult
handle_mount(Client &client, gcc_unused int argc, char *argv[]) handle_mount(Client &client, gcc_unused int argc, char *argv[])
{ {
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
class Client; class Client;
CommandResult CommandResult
handle_listmounts(Client &client, int argc, char *argv[]);
CommandResult
handle_mount(Client &client, int argc, char *argv[]); handle_mount(Client &client, int argc, char *argv[]);
#endif #endif
...@@ -95,6 +95,18 @@ public: ...@@ -95,6 +95,18 @@ public:
CompositeStorage(); CompositeStorage();
virtual ~CompositeStorage(); virtual ~CompositeStorage();
/**
* Call the given function for each mounted storage, including
* the root storage. Passes mount point URI and the a const
* Storage reference to the function.
*/
template<typename T>
void VisitMounts(T t) const {
const ScopeLock protect(mutex);
std::string uri;
VisitMounts(uri, root, t);
}
void Mount(const char *uri, Storage *storage); void Mount(const char *uri, Storage *storage);
bool Unmount(const char *uri); bool Unmount(const char *uri);
...@@ -112,6 +124,26 @@ public: ...@@ -112,6 +124,26 @@ public:
virtual const char *MapToRelativeUTF8(const char *uri) const override; virtual const char *MapToRelativeUTF8(const char *uri) const override;
private: private:
template<typename T>
void VisitMounts(std::string &uri, const Directory &directory,
T t) const {
const Storage *const storage = directory.storage;
if (storage != nullptr)
t(uri.c_str(), *storage);
if (!uri.empty())
uri.push_back('/');
const size_t uri_length = uri.length();
for (const auto &i : directory.children) {
uri.resize(uri_length);
uri.append(i.first);
VisitMounts(uri, i.second, t);
}
}
gcc_pure gcc_pure
FindResult FindStorage(const char *uri) const; FindResult FindStorage(const char *uri) const;
FindResult FindStorage(const char *uri, Error &error) const; FindResult FindStorage(const char *uri, Error &error) const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment