42#ifndef _DWMIPV6PREFIXMAP_HH_
43#define _DWMIPV6PREFIXMAP_HH_
47#include <shared_mutex>
48#include <unordered_map>
103 template <
typename T,
typename Hash = OurIpv6PrefixHash>
110 using MapType = std::unordered_map<Ipv6Prefix,T,Hash>;
111 using LengthMapType = std::map<uint8_t,uint64_t>;
117 using MapPair = std::pair<MapType,LengthMapType>;
125 _maps.first.max_load_factor(.25);
134 std::unique_lock lck(_mtx);
135 return Add(lck, pfx, value);
143 void Add(std::unique_lock<std::shared_mutex> & lck,
146 assert((lck.mutex() == &_mtx) && lck.owns_lock());
147 if (_maps.first.insert_or_assign(pfx, value).second) {
160 std::shared_lock lck(_mtx);
161 return Find(lck, pfx, value);
170 bool Find(std::shared_lock<std::shared_mutex> & lck,
173 assert((lck.mutex() == &_mtx) && lck.owns_lock());
174 return FindNoLock(pfx, value);
183 bool Find(std::unique_lock<std::shared_mutex> & lck,
186 assert((lck.mutex() == &_mtx) && lck.owns_lock());
187 return FindNoLock(pfx, value);
197 std::pair<Ipv6Prefix,T> & value)
const
199 std::shared_lock lck(_mtx);
212 std::pair<Ipv6Prefix,T> & value)
const
214 assert((lck.mutex() == &_mtx) && lck.owns_lock());
215 return FindLongestNoLock(addr, value);
227 std::pair<Ipv6Prefix,T> & value)
const
229 assert((lck.mutex() == &_mtx) && lck.owns_lock());
230 return FindLongestNoLock(addr, value);
240 std::vector<std::pair<Ipv6Prefix,T>> & values)
const
242 std::shared_lock lck(_mtx);
255 std::vector<std::pair<Ipv6Prefix,T>> & values)
const
257 assert((lck.mutex() == &_mtx) && lck.owns_lock());
258 return FindMatchesNoLock(addr, values);
270 std::vector<std::pair<Ipv6Prefix,T>> & values)
const
272 assert((lck.mutex() == &_mtx) && lck.owns_lock());
273 return FindMatchesNoLock(addr, values);
282 std::unique_lock lck(_mtx);
291 bool Remove(std::unique_lock<std::shared_mutex> & lck,
294 assert((lck.mutex() == &_mtx) && lck.owns_lock());
296 auto it = _maps.first.find(pfx);
297 if (it != _maps.first.end()) {
298 _maps.first.erase(it);
299 auto lit = _maps.second.find(pfx.
MaskLength());
301 if (0 == lit->second) {
302 _maps.second.erase(lit);
314 std::unique_lock lck(_mtx);
322 void Clear(std::unique_lock<std::shared_mutex> & lck)
324 assert((lck.mutex() == &_mtx) && lck.owns_lock());
326 _maps.second.clear();
335 std::shared_lock lck(_mtx);
343 bool Empty(std::shared_lock<std::shared_mutex> & lck)
const
345 assert((lck.mutex() == &_mtx) && lck.owns_lock());
346 return _maps.first.empty();
353 bool Empty(std::unique_lock<std::shared_mutex> & lck)
const
355 assert((lck.mutex() == &_mtx) && lck.owns_lock());
356 return _maps.first.empty();
362 std::istream &
Read(std::istream & is)
364 std::unique_lock lck(_mtx);
371 std::ostream &
Write(std::ostream & os)
const
373 std::shared_lock lck(_mtx);
383 std::unique_lock lck(_mtx);
393 std::shared_lock lck(_mtx);
403 std::unique_lock lck(_mtx);
413 std::shared_lock lck(_mtx);
425 std::unique_lock lck(_mtx);
437 std::shared_lock lck(_mtx);
449 std::unique_lock lck(_mtx);
461 std::shared_lock lck(_mtx);
471 std::shared_lock lck(_mtx);
479 bool Read(boost::asio::ip::tcp::socket & s,
480 boost::system::error_code & ec)
482 std::unique_lock lck(_mtx);
490 bool Read(boost::asio::local::stream_protocol::socket & s,
491 boost::system::error_code & ec)
493 std::unique_lock lck(_mtx);
501 bool Read(boost::asio::generic::stream_protocol::socket & s,
502 boost::system::error_code & ec)
504 std::unique_lock lck(_mtx);
512 bool Write(boost::asio::ip::tcp::socket & s,
513 boost::system::error_code & ec)
const
515 std::shared_lock lck(_mtx);
523 bool Write(boost::asio::local::stream_protocol::socket & s,
524 boost::system::error_code & ec)
const
526 std::shared_lock lck(_mtx);
534 bool Write(boost::asio::generic::stream_protocol::socket & s,
535 boost::system::error_code & ec)
const
537 std::shared_lock lck(_mtx);
554 return std::shared_lock(_mtx);
572 return std::unique_lock(_mtx);
576 mutable std::shared_mutex _mtx;
582 bool FindNoLock(
const Ipv6Prefix & pfx, T & value)
const
585 auto it = _maps.first.find(pfx);
586 if (it != _maps.first.end()) {
596 bool FindLongestNoLock(
const Ipv6Address & addr,
597 std::pair<Ipv6Prefix,T> & value)
const
600 value.first.Set(addr, 128);
601 for (
auto lit = _maps.second.rbegin();
602 lit != _maps.second.rend(); ++lit) {
603 value.first.MaskLength(lit->first);
604 auto it = _maps.first.find(value.first);
605 if (it != _maps.first.end()) {
606 value.second = it->second;
617 bool FindMatchesNoLock(
const Ipv6Address & addr,
618 std::vector<std::pair<Ipv6Prefix,T>> & values)
const
621 std::pair<Ipv6Prefix,T> value;
622 for (
auto lit = _maps.second.rbegin();
623 lit != _maps.second.rend(); ++lit) {
624 Ipv6Prefix pfx(addr, lit->first);
625 auto it = _maps.first.find(pfx);
626 if (it != _maps.first.end()) {
628 value.second = it->second;
629 values.push_back(value);
632 return (! values.empty());
Dwm::ASIO class declaration.
Dwm::BZ2IO class declaration.
Dwm::DescriptorIO class declaration.
Dwm::FileIO class declaration.
Dwm::GZIO class definition.
Dwm::IOUtils class declaration and implementation.
Dwm::Ipv6Prefix class definition.
Dwm::StreamIO class declaration.
static bool Write(boost::asio::ip::tcp::socket &s, uint8_t value, boost::system::error_code &ec)
Write value to the given socket s.
static bool Read(boost::asio::ip::tcp::socket &s, uint8_t &value, boost::system::error_code &ec)
Reads value from the given socket s.
static int BZRead(BZFILE *bzf, char &c)
Reads from bzf.
static int BZWrite(BZFILE *bzf, char c)
Writes c to bzf.
static ssize_t Write(int fd, char c)
Writes c to fd.
static ssize_t Read(int fd, char &c)
Reads c from fd.
static size_t Write(FILE *f, char c)
Writes c to f.
static size_t Read(FILE *f, char &c)
Reads c from f.
static int Write(gzFile gzf, char c)
Writes c to gzf.
static int Read(gzFile gzf, char &c)
Reads from gzf.
static uint64_t StreamedLength(char c)
Returns the number of bytes that would be written if we called Write() for a char.
Definition DwmIOUtils.hh:85
This class encapsulates an IPv6 address.
Definition DwmIpv6Address.hh:64
A wrapper around an unordered_map of T keyed by Ipv6Prefix using Hash as the hash function.
Definition DwmIpv6PrefixMap.hh:105
uint64_t StreamedLength() const
Returns the number of bytes that would be written if the Ipv6PrefixMap was written to a FILE,...
Definition DwmIpv6PrefixMap.hh:469
bool Write(boost::asio::ip::tcp::socket &s, boost::system::error_code &ec) const
Writes the Ipv6PrefixMap to s.
Definition DwmIpv6PrefixMap.hh:512
bool Empty() const
Returns true if the map is empty.
Definition DwmIpv6PrefixMap.hh:333
std::pair< MapType, LengthMapType > MapPair
Internally we keep our maps in a pair.
Definition DwmIpv6PrefixMap.hh:117
std::istream & Read(std::istream &is)
Reads the Ipv6PrefixMap from an istream. Returns the istream.
Definition DwmIpv6PrefixMap.hh:362
bool Write(boost::asio::local::stream_protocol::socket &s, boost::system::error_code &ec) const
Writes the Ipv6PrefixMap to s.
Definition DwmIpv6PrefixMap.hh:523
bool Find(const Ipv6Prefix &pfx, T &value) const
Find the entry with key pfx.
Definition DwmIpv6PrefixMap.hh:158
ssize_t Read(int fd)
Reads the Ipv6PrefixMap from file descriptor fd.
Definition DwmIpv6PrefixMap.hh:401
size_t Read(FILE *f)
Reads the Ipv6PrefixMap from f.
Definition DwmIpv6PrefixMap.hh:381
bool Read(boost::asio::local::stream_protocol::socket &s, boost::system::error_code &ec)
Reads the Ipv6PrefixMap from s.
Definition DwmIpv6PrefixMap.hh:490
bool Find(std::shared_lock< std::shared_mutex > &lck, const Ipv6Prefix &pfx, T &value) const
Find the entry with key pfx.
Definition DwmIpv6PrefixMap.hh:170
int BZRead(BZFILE *bzf)
Reads the Ipv6PrefixMap from bzf.
Definition DwmIpv6PrefixMap.hh:447
std::unique_lock< std::shared_mutex > UniqueLock()
Returns a unique lock of the Ipv6PrefixMap, in the locked state.
Definition DwmIpv6PrefixMap.hh:570
bool Empty(std::shared_lock< std::shared_mutex > &lck) const
Returns true if the map is empty.
Definition DwmIpv6PrefixMap.hh:343
void Add(std::unique_lock< std::shared_mutex > &lck, const Ipv6Prefix &pfx, const T &value)
Adds the given value to the map at key pfx.
Definition DwmIpv6PrefixMap.hh:143
bool Remove(const Ipv6Prefix &pfx)
Removes the entry for the given prefix pfx.
Definition DwmIpv6PrefixMap.hh:280
bool FindMatches(std::shared_lock< std::shared_mutex > &lck, const Ipv6Address &addr, std::vector< std::pair< Ipv6Prefix, T > > &values) const
Find all matches for the given IPv6 address addr.
Definition DwmIpv6PrefixMap.hh:253
bool FindLongest(const Ipv6Address &addr, std::pair< Ipv6Prefix, T > &value) const
Find the longest match for the given IPv6 address addr.
Definition DwmIpv6PrefixMap.hh:196
Ipv6PrefixMap()
Default constructor.
Definition DwmIpv6PrefixMap.hh:122
void Clear()
Clears the map.
Definition DwmIpv6PrefixMap.hh:312
bool Write(boost::asio::generic::stream_protocol::socket &s, boost::system::error_code &ec) const
Writes the Ipv6PrefixMap to s.
Definition DwmIpv6PrefixMap.hh:534
bool Read(boost::asio::ip::tcp::socket &s, boost::system::error_code &ec)
Reads the Ipv6PrefixMap from s.
Definition DwmIpv6PrefixMap.hh:479
std::ostream & Write(std::ostream &os) const
Writes the Ipv6PrefixMap to an ostream. Returns the ostream.
Definition DwmIpv6PrefixMap.hh:371
std::unordered_map< Ipv6Prefix, T, Hash > MapType
The types of our encapsulated containers.
Definition DwmIpv6PrefixMap.hh:110
bool Find(std::unique_lock< std::shared_mutex > &lck, const Ipv6Prefix &pfx, T &value) const
Find the entry with key pfx.
Definition DwmIpv6PrefixMap.hh:183
ssize_t Write(int fd) const
Writes the Ipv6PrefixMap to file descriptor fd.
Definition DwmIpv6PrefixMap.hh:411
bool FindLongest(std::shared_lock< std::shared_mutex > &lck, const Ipv6Address &addr, std::pair< Ipv6Prefix, T > &value) const
Find the longest match for the given IPv6 address addr.
Definition DwmIpv6PrefixMap.hh:210
std::shared_lock< std::shared_mutex > SharedLock() const
Returns a shared lock of the Ipv6PrefixMap, in the locked state.
Definition DwmIpv6PrefixMap.hh:552
bool Remove(std::unique_lock< std::shared_mutex > &lck, const Ipv6Prefix &pfx)
Removes the entry for the given prefix pfx.
Definition DwmIpv6PrefixMap.hh:291
int Write(gzFile gzf) const
Writes the Ipv6PrefixMap to gzf.
Definition DwmIpv6PrefixMap.hh:435
bool FindLongest(std::unique_lock< std::shared_mutex > &lck, const Ipv6Address &addr, std::pair< Ipv6Prefix, T > &value) const
Find the longest match for the given IPv6 address addr.
Definition DwmIpv6PrefixMap.hh:225
bool Empty(std::unique_lock< std::shared_mutex > &lck) const
Returns true if the map is empty.
Definition DwmIpv6PrefixMap.hh:353
int BZWrite(BZFILE *bzf) const
Writes the Ipv6PrefixMap to bzf.
Definition DwmIpv6PrefixMap.hh:459
void Add(const Ipv6Prefix &pfx, const T &value)
Adds the given value to the map at key pfx.
Definition DwmIpv6PrefixMap.hh:132
int Read(gzFile gzf)
Reads the Ipv6PrefixMap from gzf.
Definition DwmIpv6PrefixMap.hh:423
void Clear(std::unique_lock< std::shared_mutex > &lck)
Clears the map.
Definition DwmIpv6PrefixMap.hh:322
bool Read(boost::asio::generic::stream_protocol::socket &s, boost::system::error_code &ec)
Reads the Ipv6PrefixMap from s.
Definition DwmIpv6PrefixMap.hh:501
size_t Write(FILE *f) const
Writes the Ipv6PrefixMap to f.
Definition DwmIpv6PrefixMap.hh:391
bool FindMatches(const Ipv6Address &addr, std::vector< std::pair< Ipv6Prefix, T > > &values) const
Find all matches for the given IPv6 address addr.
Definition DwmIpv6PrefixMap.hh:239
bool FindMatches(std::unique_lock< std::shared_mutex > &lck, const Ipv6Address &addr, std::vector< std::pair< Ipv6Prefix, T > > &values) const
Find all matches for the given IPv6 address addr.
Definition DwmIpv6PrefixMap.hh:268
This class encapsulates an IPv6 network prefix.
Definition DwmIpv6Prefix.hh:52
uint64_t Hash() const
Given that the number of IPv6 addresses I typically deal with is nowhere near 4 billion,...
Definition DwmIpv6Prefix.hh:255
uint8_t MaskLength() const
Returns the netmask length.
Definition DwmIpv6Prefix.hh:95
static std::istream & Read(std::istream &is, char &c)
Reads c from is. Returns is.
static std::ostream & Write(std::ostream &os, char c)
Writes c to os. Returns os.
Default hash for our unordered_map in Ipv6PrefixMap.
Definition DwmIpv6PrefixMap.hh:87