aboutsummaryrefslogtreecommitdiffstats
path: root/messagebus/src/vespa/messagebus/routing/routingcontext.h
blob: 21853bd1509469f0f5d9f35dc0f9283fba37c570 (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once

#include "routingnodeiterator.h"
#include <vespa/messagebus/context.h>
#include <vespa/slobrok/imirrorapi.h>
#include <set>

namespace mbus {

class RoutingNode;
class PolicyDirective;
class MessageBus;
class Message;
class Error;

/**
 * This context object is what is seen by {@link RoutingPolicy} when doing both select() and merge(). It
 * contains the necessary accessors to everything a policy is expected to need. An instance of this is created
 * for every {@link RoutingNode} that contains a policy.
 */
class RoutingContext {
private:
    RoutingNode       &_node;
    Context            _context;
    uint32_t           _directive;
    bool               _selectOnRetry;
    std::set<uint32_t> _consumableErrors;

public:
    /**
     * Constructs a new routing context for a given routing node and hop.
     *
     * @param node      The owning routing node.
     * @param directive The index to the policy directive of the hop.
     */
    RoutingContext(RoutingNode &node, uint32_t directive);
    RoutingContext(const RoutingContext &) = delete;
    RoutingContext(RoutingContext &&) = delete;
    RoutingContext & operator=(const RoutingContext &) = delete;
    RoutingContext & operator=(RoutingContext &&) = delete;
    ~RoutingContext();

    /**
     * Returns whether or not this hop has any configured recipients.
     *
     * @return True if there is at least one recipient.
     */
    [[nodiscard]] bool hasRecipients() const;

    /**
     * Returns the number of configured recipients for this hop.
     *
     * @return The recipient count.
     */
    [[nodiscard]] uint32_t getNumRecipients() const;

    /**
     * Returns the configured recipient at the given index.
     *
     * @param idx The index of the recipient to return.
     * @return The reipient at the given index.
     */
    [[nodiscard]] const Route &getRecipient(uint32_t idx) const;

    /**
     * Returns all configured recipients for this hop.
     *
     * @return An unmodifiable list of recipients.
     */
    [[nodiscard]] const std::vector<Route> &getAllRecipients() const;

    /**
     * Returns a list of all configured recipients whose first hop matches this.
     *
     * @param ret The list to add matched recipients to.
     */
    void getMatchedRecipients(std::vector<Route> &ret) const;

    /**
     * Returns whether or not the policy is required to reselect if resending occurs.
     *
     * @return True to invoke {@link RoutingPolicy#select(RoutingContext)} on resend.
     */
    [[nodiscard]] bool getSelectOnRetry() const { return _selectOnRetry; }

    /**
     * Sets whether or not the policy is required to reselect if resending occurs.
     *
     * @param selectOnRetry The value to set.
     * @return This, to allow chaining.
     */
    RoutingContext &setSelectOnRetry(bool selectOnRetry) {
        _selectOnRetry = selectOnRetry;
        return *this;
    }

    /**
     * Returns the route that contains the routing policy that spawned this.
     *
     * @return The route.
     */
    [[nodiscard]] const Route &getRoute() const;

    /**
     * Returns the hop that contains the routing policy that spawned this.
     *
     * @return The hop.
     */
    [[nodiscard]] const Hop &getHop() const;

    /**
     * Returns the index of the hop directive that spawned this.
     *
     * @return The directive index.
     */
    [[nodiscard]] uint32_t getDirectiveIndex() const { return _directive; }

    /**
     * Returns the policy directive that spawned this.
     *
     * @return The directive object.
     */
    [[nodiscard]] const PolicyDirective &getDirective() const;

    /**
     * Returns the part of the route string that precedes the active policy directive. This is the same as calling
     * {@link this#getHop()}.getPrefix({@link this#getDirectiveIndex()}).
     *
     * @return The hop prefix.
     */
    [[nodiscard]] string getHopPrefix() const;

    /**
     * Returns the remainder of the route string immediately following the active policy directive. This is the same as
     * calling {@link this#getHop()}.getSuffix({@link this#getDirectiveIndex()}).
     *
     * @return The hop suffix.
     */
    [[nodiscard]] string getHopSuffix() const;

    /**
     * Returns the routing specific context object.
     *
     * @return The context.
     */
    Context &getContext() { return _context; }

    /**
     * Returns a const reference to the routing specific context object.
     *
     * @return The context.
     */
    [[nodiscard]] const Context &getContext() const { return _context; }

    /**
     * Sets a routing specific context object that will be available at merge().
     *
     * @param context An arbitrary object.
     * @return This, to allow chaining.
     */
    RoutingContext &setContext(const Context &ctx) {
        _context = ctx;
        return *this;
    }

    /**
     * Returns the message being routed.
     *
     * @return The message.
     */
    [[nodiscard]] const Message &getMessage() const;

    /**
     * Adds a string to the trace of the message being routed.
     *
     * @param level The level of the trace note.
     * @param note  The note to add.
     */
    void trace(uint32_t level, const string &note);

    /**
     * Returns the reply generated by the associated routing policy.
     *
     * @return The reply.
     */
    [[nodiscard]] const Reply &getReply() const;

    /**
     * Sets the reply generated by the associated routing policy.
     *
     * @param reply The reply to set.
     * @return This, to allow chaining.
     */
    RoutingContext &setReply(std::unique_ptr<Reply> reply);

    /**
     * This is a convenience method to call {@link #setError(Error)}.
     *
     * @param code The code of the error to set.
     * @param msg  The message of the error to set.
     * @return This, to allow chaining.
     */
    RoutingContext &setError(uint32_t code, const string &msg);

    /**
     * This is a convenience method to assign an {@link EmptyReply} containing a single error to this. This also fiddles
     * with the trace object so that the error gets written to it.
     *
     * @param err The error to set.
     * @return This, to allow chaining.
     * @see #setReply(Reply)
     */
    RoutingContext &setError(const Error &err);

    /**
     * Returns the message bus instance on which this is running.
     *
     * @return The message bus.
     */
    MessageBus &getMessageBus();

    /**
     * Returns whether or not the owning routing node has any child nodes.
     *
     * @return True if there is at least one child.
     */
    [[nodiscard]] bool hasChildren() const;

    /**
     * Returns the number of children the owning routing node has.
     *
     * @return The child count.
     */
    [[nodiscard]] uint32_t getNumChildren() const;

    /**
     * Returns an iterator for the child routing nodes.
     *
     * @return The iterator.
     */
    RoutingNodeIterator getChildIterator();

    /**
     * Adds a child routing context to this based on a given route. This is the typical entry point a policy will use to
     * select recipients during a {@link RoutingPolicy#select(RoutingContext)} invocation.
     *
     * @param route The route to contain in the child context.
     */
    void addChild(Route route);

    /**
     * This is a convenience method to more easily add a list of children to this. It will simply call the {@link
     * this#addChild} method for each element in the list.
     *
     * @param routes A list of routes to add as children.
     */
    void addChildren(std::vector<Route> routes);

    /**
     * Returns the local mirror of the system's name server.
     *
     * @return The mirror api.
     */
    [[nodiscard]] const slobrok::api::IMirrorAPI &getMirror() const;

    /**
     * Adds the given error code to the list of codes that the associated routing policy <u>may</u> consume. This is
     * used to verify whether or not a resolved routing tree can succeed if sent. Because verification is only done
     * before sending, the error types that must be added here are only those that can be generated by message bus
     * itself.
     *
     * @param errorCode The code that might be consumed.
     * @see RoutingNode#hasUnconsumedErrors()
     * @see com.yahoo.messagebus.ErrorCode
     */
    void addConsumableError(uint32_t errorCode);

    /**
     * Returns whether or not the given error code <u>may</u> be consumed by the associated routing policy.
     *
     * @param errorCode The code to check.
     * @return True if the code may be consumed.
     * @see this#addConsumableError(int)
     */
    bool isConsumableError(uint32_t errorCode);
};

} // namespace mbus