1 // Copyright (C) 2018-2019,2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef SERVER_SELECTOR_H
8 #define SERVER_SELECTOR_H
9 
10 #include <cc/server_tag.h>
11 #include <set>
12 #include <string>
13 
14 namespace isc {
15 namespace db {
16 
17 /// @brief Server selector for associating objects in a database with
18 /// specific servers.
19 ///
20 /// Configuration information stored in the configuration backends can be
21 /// associated with selected servers, all servers or no particular server.
22 /// For example: a particular subnet definition in the database may be
23 /// associated with one server or can be shared by multiple servers.
24 /// In the latter case, a subnet may be associated with a subset of
25 /// servers or all servers. An administrator may also add the
26 /// configuration data into the database and do not associate this data
27 /// with any particular server.
28 ///
29 /// When fetching the configuration data from a database or when storing
30 /// data in the database there is a need to specify which servers this
31 /// data is associated with. The @c ServerSelector class represents
32 /// such associations.
33 ///
34 /// It includes three modes of selection: UNASSIGNED, ALL and SUBSET and
35 /// several factory functions making associations described above.
36 ///
37 /// The @c ServerSelector class should be used in objects derived from
38 /// @c BaseConfigBackendPool and in objects derived from
39 /// @c BaseConfigBackend to indicate which servers the specific calls
40 /// exposed by these objects refer to.
41 ///
42 /// @todo Add server selector for selecting only those configuration
43 /// elements that are associated with all servers (and not with any
44 /// particular server tags). Translating this to SQL queries it would
45 /// probably be an empty or non-existing server tag.
46 class ServerSelector {
47 public:
48 
49     /// @brief Type of the server selection.
50     enum class Type {
51         UNASSIGNED,
52         ALL,
53         SUBSET,
54         ANY
55     };
56 
57     /// @brief Factory returning "unassigned" server selector.
UNASSIGNED()58     static ServerSelector UNASSIGNED() {
59         ServerSelector selector(Type::UNASSIGNED);
60         return (selector);
61     }
62 
63     /// @brief Factory returning "all servers" selector.
ALL()64     static ServerSelector ALL() {
65         ServerSelector selector(Type::ALL);
66         return (selector);
67     }
68 
69     /// @brief Factory returning selector of one server.
70     ///
71     /// @param server_tag tag of the single server to be selected.
ONE(const std::string & server_tag)72     static ServerSelector ONE(const std::string& server_tag) {
73         ServerSelector selector((data::ServerTag(server_tag)));
74         return (selector);
75     }
76 
77     /// @brief Factory returning "multiple servers" selector.
78     ///
79     /// @param server_tags set of server tags to be selected.
80     /// @throw InvalidOperation if no server tags provided.
81     static ServerSelector MULTIPLE(const std::set<std::string>& server_tags);
82 
83     /// @brief Factory returning "any server" selector.
ANY()84     static ServerSelector ANY() {
85         ServerSelector selector(Type::ANY);
86         return (selector);
87     }
88 
89     /// @brief Returns type of the selector.
getType()90     Type getType() const {
91         return (type_);
92     }
93 
94     /// @brief Returns tags associated with the selector.
95     ///
96     /// @return server tags for multiple selections and for one server,
97     /// empty set for all servers and and unassigned.
getTags()98     std::set<data::ServerTag> getTags() const {
99         return (tags_);
100     }
101 
102     /// @brief Convenience method checking if the server selector has no tags.
103     ///
104     /// @return true when the server selector has no tags, false otherwise.
hasNoTags()105     bool hasNoTags() const {
106         return (tags_.empty());
107     }
108 
109     /// @brief Convenience method checking if the server selector is "unassigned".
110     ///
111     /// @return true if the selector is "unassigned", false otherwise.
amUnassigned()112     bool amUnassigned() const {
113         return (getType() == Type::UNASSIGNED);
114     }
115 
116     /// @brief Convenience method checking if the server selector is "all".
117     ///
118     /// @return true if the selector is "all", false otherwise.
amAll()119     bool amAll() const {
120         return (getType() == Type::ALL);
121     }
122 
123     /// @brief Convenience method checking if the server selector is "any".
124     ///
125     /// @return true if the selector is "any", false otherwise.
amAny()126     bool amAny() const {
127         return (getType() == Type::ANY);
128     }
129 
130     /// @brief Convenience method checking if the server selector has multiple tags.
131     ///
132     /// @return true if it has multiple tags, false otherwise.
hasMultipleTags()133     bool hasMultipleTags() const {
134         return (tags_.size() > 1);
135     }
136 
137 private:
138 
139     /// @brief Constructor used for "unassigned" and "all" selection types.
140     ///
141     /// @param type selector type.
142     explicit ServerSelector(const Type& type);
143 
144     /// @brief Constructor used for selecting a single server.
145     ///
146     /// @param server_tag tag of the server to be selected.
147     explicit ServerSelector(const data::ServerTag& server_tag);
148 
149     /// @brief Constructor used for selecting multiple servers.
150     ///
151     /// @param server_tags set of server tags.
152     explicit ServerSelector(const std::set<data::ServerTag>& server_tags);
153 
154     /// @brief Selection type used.
155     Type type_;
156 
157     /// @brief Holds tags of explicitly selected servers.
158     std::set<data::ServerTag> tags_;
159 };
160 
161 
162 } // end of namespace isc::db
163 } // end of namespace isc
164 
165 #endif
166