aboutsummaryrefslogtreecommitdiffstats
path: root/fnet/src/vespa/fnet/channellookup.cpp
blob: 6af5a574e9b46c32c5c88d86424ec9915a382d39 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "channellookup.h"
#include "vespa/fnet/channel.h"
#include "controlpacket.h"
#include <vespa/vespalib/stllike/hash_map.hpp>
#include <cassert>

namespace fnet {

struct ChannelMap : public vespalib::hash_map<uint32_t, FNET_Channel *> {
    using Parent = vespalib::hash_map<uint32_t, FNET_Channel *>;
    ChannelMap(size_t sz) : Parent(sz) { }
};

}
using fnet::ChannelMap;

FNET_ChannelLookup::FNET_ChannelLookup(uint32_t hashSize)
    : _map(std::make_unique<ChannelMap>(hashSize))
{
    assert(hashSize > 0);
}


FNET_ChannelLookup::~FNET_ChannelLookup()
{
    assert(_map->empty());
}


void
FNET_ChannelLookup::Register(FNET_Channel *channel)
{
    assert(channel->GetHandler() != nullptr);
    (*_map)[channel->GetID()] = channel;
}


FNET_Channel*
FNET_ChannelLookup::Lookup(uint32_t id)
{
    auto found = _map->find(id);
    return ((found != _map->end()) ? found->second : nullptr);
}


std::vector<FNET_Channel::UP>
FNET_ChannelLookup::Broadcast(FNET_ControlPacket *cpacket)
{
    std::vector<uint32_t> toRemove;
    std::vector<FNET_Channel::UP> toFree;
    for (const auto & pair : *_map) {
        FNET_Channel *ch = pair.second;
        FNET_IPacketHandler::HP_RetCode hp_rc = ch->Receive(cpacket);
        if (hp_rc > FNET_IPacketHandler::FNET_KEEP_CHANNEL) {
            toRemove.push_back(pair.first);
            if (hp_rc == FNET_IPacketHandler::FNET_FREE_CHANNEL) {
                toFree.emplace_back(ch);
            }
        }
    }
    for (uint32_t id : toRemove) {
        _map->erase(id);
    }
    return toFree;
}

bool
FNET_ChannelLookup::Unregister(FNET_Channel *channel)
{
    auto found = _map->find(channel->GetID());
    if (found == _map->end()) {
        return false;
    }
    _map->erase(found);
    return true;
}