lib/nfs/Manager: use boost::intrusive::map
Reduce overhead for storing the key twice, and more overhead while looking up the connection to remove it after a failure.
This commit is contained in:
parent
952fe98796
commit
f9ad73598b
@ -22,12 +22,48 @@
|
|||||||
#include "event/Loop.hxx"
|
#include "event/Loop.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
NfsManager::ManagedConnection::OnNfsConnectionError(Error &&error)
|
NfsManager::ManagedConnection::OnNfsConnectionError(Error &&error)
|
||||||
{
|
{
|
||||||
FormatError(error, "NFS error on %s:%s", GetServer(), GetExportName());
|
FormatError(error, "NFS error on %s:%s", GetServer(), GetExportName());
|
||||||
|
|
||||||
manager.connections.erase(Key(GetServer(), GetExportName()));
|
manager.connections.erase(manager.connections.iterator_to(*this));
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
NfsManager::Compare::operator()(const LookupKey a,
|
||||||
|
const ManagedConnection &b) const
|
||||||
|
{
|
||||||
|
int result = strcmp(a.server, b.GetServer());
|
||||||
|
if (result != 0)
|
||||||
|
return result < 0;
|
||||||
|
|
||||||
|
result = strcmp(a.export_name, b.GetExportName());
|
||||||
|
return result < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
NfsManager::Compare::operator()(const ManagedConnection &a,
|
||||||
|
const LookupKey b) const
|
||||||
|
{
|
||||||
|
int result = strcmp(a.GetServer(), b.server);
|
||||||
|
if (result != 0)
|
||||||
|
return result < 0;
|
||||||
|
|
||||||
|
result = strcmp(a.GetExportName(), b.export_name);
|
||||||
|
return result < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NfsManager::~NfsManager()
|
||||||
|
{
|
||||||
|
assert(loop.IsInside());
|
||||||
|
|
||||||
|
connections.clear_and_dispose([](ManagedConnection *c){
|
||||||
|
delete c;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
NfsConnection &
|
NfsConnection &
|
||||||
@ -37,21 +73,15 @@ NfsManager::GetConnection(const char *server, const char *export_name)
|
|||||||
assert(export_name != nullptr);
|
assert(export_name != nullptr);
|
||||||
assert(loop.IsInside());
|
assert(loop.IsInside());
|
||||||
|
|
||||||
const std::string key = Key(server, export_name);
|
Map::insert_commit_data hint;
|
||||||
|
auto result = connections.insert_check(LookupKey{server, export_name},
|
||||||
#if defined(__GNUC__) && !defined(__clang__) && !GCC_CHECK_VERSION(4,8)
|
Compare(), hint);
|
||||||
/* std::map::emplace() not available; this hack uses the move
|
if (result.second) {
|
||||||
constructor */
|
auto c = new ManagedConnection(*this, loop,
|
||||||
auto e = connections.insert(std::make_pair(key,
|
server, export_name);
|
||||||
ManagedConnection(*this, loop,
|
connections.insert_commit(*c, hint);
|
||||||
server,
|
return *c;
|
||||||
export_name)));
|
} else {
|
||||||
#else
|
return *result.first;
|
||||||
auto e = connections.emplace(std::piecewise_construct,
|
}
|
||||||
std::forward_as_tuple(key),
|
|
||||||
std::forward_as_tuple(*this, loop,
|
|
||||||
server,
|
|
||||||
export_name));
|
|
||||||
#endif
|
|
||||||
return e.first->second;
|
|
||||||
}
|
}
|
||||||
|
@ -24,15 +24,21 @@
|
|||||||
#include "Connection.hxx"
|
#include "Connection.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <string>
|
#include <boost/intrusive/set.hpp>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A manager for NFS connections. Handles multiple connections to
|
* A manager for NFS connections. Handles multiple connections to
|
||||||
* multiple NFS servers.
|
* multiple NFS servers.
|
||||||
*/
|
*/
|
||||||
class NfsManager {
|
class NfsManager {
|
||||||
class ManagedConnection final : public NfsConnection {
|
struct LookupKey {
|
||||||
|
const char *server;
|
||||||
|
const char *export_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ManagedConnection final
|
||||||
|
: public NfsConnection,
|
||||||
|
public boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
|
||||||
NfsManager &manager;
|
NfsManager &manager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -42,39 +48,44 @@ class NfsManager {
|
|||||||
:NfsConnection(_loop, _server, _export_name),
|
:NfsConnection(_loop, _server, _export_name),
|
||||||
manager(_manager) {}
|
manager(_manager) {}
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__) && !GCC_CHECK_VERSION(4,8)
|
|
||||||
/* needed due to lack of std::map::emplace() */
|
|
||||||
ManagedConnection(ManagedConnection &&other)
|
|
||||||
:NfsConnection(std::move(other)),
|
|
||||||
manager(other.manager) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* virtual methods from NfsConnection */
|
/* virtual methods from NfsConnection */
|
||||||
void OnNfsConnectionError(Error &&error) override;
|
void OnNfsConnectionError(Error &&error) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Compare {
|
||||||
|
gcc_pure
|
||||||
|
bool operator()(const LookupKey a,
|
||||||
|
const ManagedConnection &b) const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
bool operator()(const ManagedConnection &a,
|
||||||
|
const LookupKey b) const;
|
||||||
|
};
|
||||||
|
|
||||||
EventLoop &loop;
|
EventLoop &loop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps server+":"+export_name (see method Key()) to
|
* Maps server and export_name to #ManagedConnection.
|
||||||
* #ManagedConnection.
|
|
||||||
*/
|
*/
|
||||||
std::map<std::string, ManagedConnection> connections;
|
typedef boost::intrusive::set<ManagedConnection,
|
||||||
|
boost::intrusive::compare<Compare>,
|
||||||
|
boost::intrusive::constant_time_size<false>> Map;
|
||||||
|
|
||||||
|
Map connections;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NfsManager(EventLoop &_loop)
|
NfsManager(EventLoop &_loop)
|
||||||
:loop(_loop) {}
|
:loop(_loop) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be run from EventLoop's thread.
|
||||||
|
*/
|
||||||
|
~NfsManager();
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
NfsConnection &GetConnection(const char *server,
|
NfsConnection &GetConnection(const char *server,
|
||||||
const char *export_name);
|
const char *export_name);
|
||||||
|
|
||||||
private:
|
|
||||||
gcc_pure
|
|
||||||
static std::string Key(const char *server, const char *export_name) {
|
|
||||||
return std::string(server) + ':' + export_name;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user