1 /* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 #ifndef GCS_EVENT_HANDLERS_INCLUDE
24 #define GCS_EVENT_HANDLERS_INCLUDE
25 
26 #include <set>
27 #include <vector>
28 
29 #include <mysql/gcs/gcs_control_event_listener.h>
30 #include <mysql/gcs/gcs_communication_event_listener.h>
31 
32 #include "applier.h"
33 #include "compatibility_module.h"
34 #include "gcs_plugin_messages.h"
35 #include "gcs_view_modification_notifier.h"
36 #include "plugin_constants.h"
37 #include "recovery.h"
38 #include "recovery_message.h"
39 #include "read_mode_handler.h"
40 
41 
42 /*
43  The server version in which member weight was introduced.
44  */
45 #define PRIMARY_ELECTION_MEMBER_WEIGHT_VERSION 0x050720
46 
47 /**
48   Group_member_info_pointer_comparator to guarantee uniqueness
49  */
50 struct Group_member_info_pointer_comparator
51 {
operatorGroup_member_info_pointer_comparator52   bool operator()(Group_member_info* one,
53                   Group_member_info* other) const
54   {
55     return one->has_lower_uuid(other);
56   }
57 };
58 
59 
60 /*
61   @class Plugin_gcs_events_handler
62 
63   Implementation of all GCS event handlers to the plugin
64  */
65 class Plugin_gcs_events_handler: public Gcs_communication_event_listener,
66                                  public Gcs_control_event_listener
67 {
68 public:
69   /**
70     Plugin_gcs_events_handler constructor
71 
72     It receives, via the constructor, all the necessary dependencies to work.
73   */
74   Plugin_gcs_events_handler(Applier_module_interface* applier_module,
75                             Recovery_module* recovery_module,
76                             Plugin_gcs_view_modification_notifier* vc_notifier,
77                             Compatibility_module* compatibility_manager,
78                             ulong components_stop_timeout);
79   virtual ~Plugin_gcs_events_handler();
80 
81   /*
82    Implementation of all callback methods
83    */
84   void on_message_received(const Gcs_message& message) const;
85   void on_view_changed(const Gcs_view &new_view,
86                        const Exchanged_data &exchanged_data) const;
87   Gcs_message_data* get_exchangeable_data() const;
88   void on_suspicions(const std::vector<Gcs_member_identifier>& members,
89                      const std::vector<Gcs_member_identifier>& unreachable) const;
90 
91   /**
92     Sets the component stop timeout.
93 
94     @param[in]  timeout      the timeout
95   */
set_stop_wait_timeout(ulong timeout)96   void set_stop_wait_timeout (ulong timeout){
97     stop_wait_timeout= timeout;
98   }
99 
100 private:
101   /*
102    Individual handling methods for all possible message types
103    received via on_message_received(...)
104    */
105   void handle_transactional_message(const Gcs_message& message) const;
106   void handle_certifier_message(const Gcs_message& message) const;
107   void handle_recovery_message(const Gcs_message& message) const;
108   void handle_stats_message(const Gcs_message& message) const;
109   void handle_single_primary_message(const Gcs_message& message) const;
110 
111   /*
112    Methods to act upon members after a on_view_change(...) is called
113    */
114   int update_group_info_manager(const Gcs_view& new_view,
115                                  const Exchanged_data &exchanged_data,
116                                  bool is_joining,
117                                  bool is_leaving)
118                                  const;
119   void handle_joining_members(const Gcs_view& new_view,
120                               bool is_joining,
121                               bool is_leaving)
122                               const;
123   void handle_leaving_members(const Gcs_view& new_view,
124                               bool is_joining,
125                               bool is_leaving)
126                               const;
127 
128   /**
129     This method updates the status of the members in the list according to the
130     given parameters.
131 
132     @param members               the vector with members to change the status to
133     @param status                the status to change to.
134     @param old_equal_to          change if the old status is equal to
135     @param old_different_from    change if the old status if different from
136 
137     @note When not using the old_equal_to and old_different_from parameters, you
138     can pass the Group_member_info::MEMBER_END value.
139   */
140   void
141   update_member_status(const std::vector<Gcs_member_identifier>& members,
142                        Group_member_info::Group_member_status status,
143                        Group_member_info::Group_member_status old_equal_to,
144                        Group_member_info::Group_member_status old_different_from)
145                        const;
146 
147   /**
148     This method handles the election of a new primary node when the plugin runs
149     in single primary mode.
150 
151     @note This function unsets the super read only mode on primary node
152           and sets it on secondary nodes
153   */
154   void handle_leader_election_if_needed() const;
155 
156   /**
157     Sort lower version members based on member weight if member version
158     is greater than equal to PRIMARY_ELECTION_MEMBER_WEIGHT_VERSION or uuid.
159 
160     @param all_members_info    the vector with members info
161     @param lowest_version_end  first iterator position where members version
162                                increases.
163    */
164   void sort_members_for_election(
165        std::vector<Group_member_info*>* all_members_info,
166        std::vector<Group_member_info*>::iterator lowest_version_end) const;
167 
168   /**
169     Sort members based on member_version and get first iterator position
170     where member version differs.
171 
172     @param all_members_info    the vector with members info
173 
174     @return  the first iterator position where members version increase.
175 
176     @note from the start of the list to the returned iterator, all members have
177           the lowest version in the group.
178    */
179   std::vector<Group_member_info*>::iterator
180   sort_and_get_lowest_version_member_position(
181     std::vector<Group_member_info*>* all_members_info) const;
182 
183   int
184   process_local_exchanged_data(const Exchanged_data &exchanged_data,
185                                bool is_joining)
186                                const;
187 
188   /**
189     Verifies if a certain Vector of Member Ids contains a given member id.
190 
191     @param members   the vector with members to verify
192     @param member_id the member to check if it contained.
193 
194     @return true if member_id occurs in members.
195    */
196   bool is_member_on_vector(const std::vector<Gcs_member_identifier>& members,
197                            const Gcs_member_identifier& member_id)
198                            const;
199 
200   /**
201     Checks the compatibility of the member with the group.
202     It checks:
203       1) If the number of members was exceeded
204       2) If member version is compatible with the group
205       3) If the gtid_assignment_block_size is equal to the group
206       4) If the hash algorithm used is equal to the group
207       5) If the member has more known transactions than the group
208 
209     @param number_of_members  the number of members in the new view
210 
211     @retval 0      compatible
212     @retval >0     not compatible with the group
213   */
214   int check_group_compatibility(size_t number_of_members) const;
215 
216   /**
217     When the member is joining, cycle through all members on group and see if it
218     is compatible with them.
219 
220     @return the compatibility with the group
221       @retval INCOMPATIBLE      //Versions not compatible
222       @retval COMPATIBLE        //Versions compatible
223       @retval READ_COMPATIBLE   //Member can read but not write
224    */
225   st_compatibility_types check_version_compatibility_with_group() const;
226 
227   /**
228    Method that compares the group's aggregated GTID set against the joiner
229    GTID set. These sets contain executed and received GTIDs present
230    in the relay log files belonging to each member plugin applier channel.
231 
232    @return if the joiner has more GTIDs then the group.
233      @retval 0     Joiner has less GTIDs than the group
234      @retval >0    Joiner has more GTIDS than the group
235      @retval <0    Error when processing GTID information
236  */
237   int compare_member_transaction_sets() const;
238 
239   /**
240     This method takes all the group executed sets and adds those belonging to
241     non recovering member to the view change packet
242 
243     @param[in]  joining_members     the joining members for this view
244     @param[in]  view_packet         the view change packet
245   */
246   void
247   collect_members_executed_sets(const std::vector<Gcs_member_identifier> &joining_members,
248                                 View_change_packet *view_packet) const;
249 
250   /**
251     Method that compares the member options with
252     the value of the same option on all other members.
253     It compares:
254       1) GTID assignment block size
255       2) Write set hash algorithm
256 
257     @return
258       @retval 0     Joiner has the same value as all other members
259       @retval !=0   Otherwise
260   */
261   int compare_member_option_compatibility() const;
262 
263   /**
264     This method submits a request to leave the group
265   */
266   void leave_group_on_error() const;
267 
268   /**
269     This method checks if member was expelled from the group due
270     to network failures.
271 
272     @param[in]  view        the view delivered by the GCS
273 
274     @return
275         @retval true   the member was expelled
276         @retval false  otherwise
277   */
278   bool was_member_expelled_from_group(const Gcs_view& view) const;
279 
280   /**
281     Logs member joining message to error logs from view.
282 
283     @param[in]  new_view        the view delivered by the GCS
284   */
285   void log_members_joining_message(const Gcs_view& new_view) const;
286 
287   /**
288     Logs member leaving message to error logs from view.
289 
290     @param[in]  new_view        the view delivered by the GCS
291   */
292   void log_members_leaving_message(const Gcs_view& new_view) const;
293 
294   /**
295     This function return all members present in vector of Gcs_member_identifier
296     in HOST:PORT format separated by comma.
297     Function also return PRIMARY member if any in HOST:PORT format.
298 
299     @param[in]    members      joining or leaving members for this view
300     @param[out]   all_hosts    host and port of all members from view
301     @param[out]   primary_host primary member hosts and port of all members from view
302   */
303   void get_hosts_from_view(const std::vector<Gcs_member_identifier> &members,
304                            std::string& all_hosts, std::string& primary_host) const;
305 
306   Applier_module_interface* applier_module;
307   Recovery_module* recovery_module;
308 
309   /*
310     Holds, until view can be installed, all Member information received from
311     other members
312   */
313   std::set<Group_member_info*,
314       Group_member_info_pointer_comparator>* temporary_states;
315 
316   Plugin_gcs_view_modification_notifier* view_change_notifier;
317 
318   Compatibility_module* compatibility_manager;
319 
320   /**The status of this member when it joins*/
321   st_compatibility_types* joiner_compatibility_status;
322 
323   /* Component stop timeout on shutdown */
324   ulong stop_wait_timeout;
325 
326 #ifndef DBUG_OFF
327   bool set_number_of_members_on_view_changed_to_10;
328 #endif
329 };
330 
331 #endif /* GCS_EVENT_HANDLERS_INCLUDE */
332