Commit 56eaf000 authored by Max Kellermann's avatar Max Kellermann

Partition: add client list

For efficient traversal within one partition, e.g. for distributing partition-local idle events.
parent 77271ebc
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "mixer/Volume.hxx" #include "mixer/Volume.hxx"
#include "IdleFlags.hxx" #include "IdleFlags.hxx"
#include "client/Listener.hxx" #include "client/Listener.hxx"
#include "client/Client.hxx"
#include "input/cache/Manager.hxx" #include "input/cache/Manager.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "Chrono.hxx" #include "Chrono.hxx"
#include "config.h" #include "config.h"
#include <boost/intrusive/list.hpp>
#include <string> #include <string>
#include <memory> #include <memory>
...@@ -39,6 +41,7 @@ struct Instance; ...@@ -39,6 +41,7 @@ struct Instance;
class MultipleOutputs; class MultipleOutputs;
class SongLoader; class SongLoader;
class ClientListener; class ClientListener;
class Client;
/** /**
* A partition of the Music Player Daemon. It is a separate unit with * A partition of the Music Player Daemon. It is a separate unit with
...@@ -55,6 +58,11 @@ struct Partition final : QueueListener, PlayerListener, MixerListener { ...@@ -55,6 +58,11 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
std::unique_ptr<ClientListener> listener; std::unique_ptr<ClientListener> listener;
boost::intrusive::list<Client,
boost::intrusive::base_hook<boost::intrusive::list_base_hook<boost::intrusive::tag<Partition>,
boost::intrusive::link_mode<boost::intrusive::normal_link>>>,
boost::intrusive::constant_time_size<false>> clients;
MaskMonitor global_events; MaskMonitor global_events;
struct playlist playlist; struct playlist playlist;
......
...@@ -68,7 +68,9 @@ Client::SetPartition(Partition &new_partition) noexcept ...@@ -68,7 +68,9 @@ Client::SetPartition(Partition &new_partition) noexcept
if (partition == &new_partition) if (partition == &new_partition)
return; return;
partition->clients.erase(partition->clients.iterator_to(*this));
partition = &new_partition; partition = &new_partition;
partition->clients.push_back(*this);
/* set idle flags for those subsystems which are specific to /* set idle flags for those subsystems which are specific to
the current partition to force the client to reload its the current partition to force the client to reload its
......
...@@ -52,6 +52,8 @@ class BackgroundCommand; ...@@ -52,6 +52,8 @@ class BackgroundCommand;
class Client final class Client final
: FullyBufferedSocket, : FullyBufferedSocket,
public boost::intrusive::list_base_hook<boost::intrusive::tag<Partition>,
boost::intrusive::link_mode<boost::intrusive::normal_link>>,
public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> { public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
TimerEvent timeout_event; TimerEvent timeout_event;
......
...@@ -72,6 +72,7 @@ client_new(EventLoop &loop, Partition &partition, ...@@ -72,6 +72,7 @@ client_new(EventLoop &loop, Partition &partition,
num); num);
client_list.Add(*client); client_list.Add(*client);
partition.clients.push_back(*client);
FormatInfo(client_domain, "[%u] opened from %s", FormatInfo(client_domain, "[%u] opened from %s",
num, remote.c_str()); num, remote.c_str());
...@@ -81,6 +82,7 @@ void ...@@ -81,6 +82,7 @@ void
Client::Close() noexcept Client::Close() noexcept
{ {
partition->instance.client_list->Remove(*this); partition->instance.client_list->Remove(*this);
partition->clients.erase(partition->clients.iterator_to(*this));
if (FullyBufferedSocket::IsDefined()) if (FullyBufferedSocket::IsDefined())
FullyBufferedSocket::Close(); FullyBufferedSocket::Close();
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
#include "client/Client.hxx" #include "client/Client.hxx"
#include "client/List.hxx" #include "client/List.hxx"
#include "client/Response.hxx" #include "client/Response.hxx"
#include "Instance.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "Partition.hxx"
#include <set> #include <set>
#include <string> #include <string>
...@@ -79,11 +79,7 @@ handle_channels(Client &client, gcc_unused Request args, Response &r) ...@@ -79,11 +79,7 @@ handle_channels(Client &client, gcc_unused Request args, Response &r)
std::set<std::string> channels; std::set<std::string> channels;
const auto &partition = client.GetPartition(); for (const auto &c : client.GetPartition().clients) {
for (const auto &c : *client.GetInstance().client_list) {
if (&c.GetPartition() != &partition)
continue;
const auto &subscriptions = c.GetSubscriptions(); const auto &subscriptions = c.GetSubscriptions();
channels.insert(subscriptions.begin(), channels.insert(subscriptions.begin(),
subscriptions.end()); subscriptions.end());
...@@ -125,10 +121,8 @@ handle_send_message(Client &client, Request args, Response &r) ...@@ -125,10 +121,8 @@ handle_send_message(Client &client, Request args, Response &r)
bool sent = false; bool sent = false;
const ClientMessage msg(channel_name, message_text); const ClientMessage msg(channel_name, message_text);
const auto &partition = client.GetPartition(); for (auto &c : client.GetPartition().clients)
for (auto &c : *client.GetInstance().client_list) if (c.PushMessage(msg))
if (&c.GetPartition() == &partition &&
c.PushMessage(msg))
sent = true; sent = true;
if (sent) if (sent)
......
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