1 /* Copyright (c) 2014, 2020, 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
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef MEMBER_INFO_INCLUDE
24 #define MEMBER_INFO_INCLUDE
25 
26 /*
27   The file contains declarations relevant to Member state and
28   its identification by the Protocol Client.
29 */
30 
31 /*
32   Since this file is used on unit tests includes must set here and
33   not through plugin_server_include.h.
34 */
35 
36 #include <list>
37 #include <map>
38 #include <set>
39 #include <sstream>
40 #include <string>
41 #include <vector>
42 
43 #include "my_inttypes.h"
44 #include "my_sys.h"
45 #include "plugin/group_replication/include/gcs_plugin_messages.h"
46 #include "plugin/group_replication/include/member_version.h"
47 #include "plugin/group_replication/include/plugin_psi.h"
48 #include "plugin/group_replication/include/services/notification/notification.h"
49 #include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/gcs_member_identifier.h"
50 
51 /*
52   Encoding of the group_replication_enforce_update_everywhere_checks
53   config value in the member info structure.
54 */
55 #define CNF_ENFORCE_UPDATE_EVERYWHERE_CHECKS_F 0x1
56 
57 /*
58   Encoding of the group_replication_single_primary_mode config value
59   in the member info structure.
60 */
61 #define CNF_SINGLE_PRIMARY_MODE_F 0x2
62 
63 /*
64   Valid values of lower_case_table_names are 0 - 2.
65   So when member has DEFAULT_NOT_RECEIVED value, it means its
66   lower_case_table_names value is not known.
67 */
68 #define DEFAULT_NOT_RECEIVED_LOWER_CASE_TABLE_NAMES 65540
69 #ifndef DBUG_OFF
70 #define SKIP_ENCODING_LOWER_CASE_TABLE_NAMES 65541
71 #endif
72 
73 /*
74   @class Group_member_info
75 
76   Describes all the properties of a group member
77 */
78 class Group_member_info : public Plugin_gcs_message {
79  public:
80   enum enum_payload_item_type {
81     // This type should not be used anywhere.
82     PIT_UNKNOWN = 0,
83 
84     // Length of the payload item: variable
85     PIT_HOSTNAME = 1,
86 
87     // Length of the payload item: 2 bytes
88     PIT_PORT = 2,
89 
90     // Length of the payload item: variable
91     PIT_UUID = 3,
92 
93     // Length of the payload item: variable
94     PIT_GCS_ID = 4,
95 
96     // Length of the payload item: 1 byte
97     PIT_STATUS = 5,
98 
99     // Length of the payload item: 4 bytes
100     PIT_VERSION = 6,
101 
102     // Length of the payload item: 2 bytes
103     PIT_WRITE_SET_EXTRACTION_ALGORITHM = 7,
104 
105     // Length of the payload item: variable
106     PIT_EXECUTED_GTID = 8,
107 
108     // Length of the payload item: variable
109     PIT_RETRIEVED_GTID = 9,
110 
111     // Length of the payload item: 8 bytes
112     PIT_GTID_ASSIGNMENT_BLOCK_SIZE = 10,
113 
114     // length of the role item: 1 byte
115     PIT_MEMBER_ROLE = 11,
116 
117     // length of the configuration flags: 4 bytes
118     PIT_CONFIGURATION_FLAGS = 12,
119 
120     // length of the conflict detection enabled: 1 byte
121     PIT_CONFLICT_DETECTION_ENABLE = 13,
122 
123     // Length of the payload item: 2 bytes
124     PIT_MEMBER_WEIGHT = 14,
125 
126     // Length of the payload item: 2 bytes
127     PIT_LOWER_CASE_TABLE_NAME = 15,
128 
129     // Length of the payload item: 1 bytes
130     PIT_GROUP_ACTION_RUNNING = 16,
131 
132     // Length of the payload item: 1 bytes
133     PIT_PRIMARY_ELECTION_RUNNING = 17,
134 
135     // Length of the payload item: 1 bytes
136     PIT_DEFAULT_TABLE_ENCRYPTION = 18,
137 
138     // Length of the payload item: variable
139     PIT_PURGED_GTID = 19,
140 
141     // Length of the payload item: variable
142     PIT_RECOVERY_ENDPOINTS = 20,
143 
144     // No valid type codes can appear after this one.
145     PIT_MAX = 21
146   };
147 
148   /*
149    @enum Member_recovery_status
150 
151    This enumeration describes all the states that a member can assume while in a
152    group.
153    */
154   typedef enum {
155     MEMBER_ONLINE = 1,
156     MEMBER_OFFLINE,
157     MEMBER_IN_RECOVERY,
158     MEMBER_ERROR,
159     MEMBER_UNREACHABLE,
160     MEMBER_END  // the end of the enum
161   } Group_member_status;
162 
163   /*
164     @enum Group_member_role
165 
166     This enumeration describes all the roles a server can have.
167   */
168   typedef enum {
169     MEMBER_ROLE_PRIMARY = 1,
170     MEMBER_ROLE_SECONDARY,
171     MEMBER_ROLE_END
172   } Group_member_role;
173 
174   /**
175     Group_member_info constructor
176 
177     @param[in] hostname_arg                           member hostname
178     @param[in] port_arg                               member port
179     @param[in] uuid_arg                               member uuid
180     @param[in] write_set_extraction_algorithm         write set extraction
181     algorithm
182     @param[in] gcs_member_id_arg                      member GCS member
183     identifier
184     @param[in] status_arg                             member Recovery status
185     @param[in] member_version_arg                     member version
186     @param[in] gtid_assignment_block_size_arg         member gtid assignment
187     block size
188     @param[in] role_arg                               member role within the
189     group
190     @param[in] in_single_primary_mode                 is member in single mode
191     @param[in] has_enforces_update_everywhere_checks  has member enforce update
192     check
193     @param[in] member_weight_arg                      member_weight
194     @param[in] lower_case_table_names_arg             lower case table names
195     @param[in] psi_mutex_key_arg                      mutex key
196     @param[in] default_table_encryption_arg           default_table_encryption
197     @param[in] recovery_endpoints_arg                 recovery endpoints
198     advertised
199    */
200   Group_member_info(const char *hostname_arg, uint port_arg,
201                     const char *uuid_arg, int write_set_extraction_algorithm,
202                     const std::string &gcs_member_id_arg,
203                     Group_member_info::Group_member_status status_arg,
204                     Member_version &member_version_arg,
205                     ulonglong gtid_assignment_block_size_arg,
206                     Group_member_info::Group_member_role role_arg,
207                     bool in_single_primary_mode,
208                     bool has_enforces_update_everywhere_checks,
209                     uint member_weight_arg, uint lower_case_table_names_arg,
210                     bool default_table_encryption_arg,
211                     const char *recovery_endpoints_arg,
212                     PSI_mutex_key psi_mutex_key_arg =
213                         key_GR_LOCK_group_member_info_update_lock);
214 
215   /**
216     Copy constructor
217 
218     @param other source of the copy
219    */
220   Group_member_info(Group_member_info &other);
221 
222   /**
223    * Group_member_info raw data constructor
224    *
225    * @param[in] data raw data
226    * @param[in] len raw data length
227    * @param[in] psi_mutex_key_arg                      mutex key
228    */
229   Group_member_info(const uchar *data, size_t len,
230                     PSI_mutex_key psi_mutex_key_arg =
231                         key_GR_LOCK_group_member_info_update_lock);
232 
233   /**
234     Destructor
235    */
236   virtual ~Group_member_info();
237 
238   /**
239     Update Group_member_info.
240 
241     @param[in] hostname_arg                           member hostname
242     @param[in] port_arg                               member port
243     @param[in] uuid_arg                               member uuid
244     @param[in] write_set_extraction_algorithm         write set extraction
245     algorithm
246     @param[in] gcs_member_id_arg                      member GCS member
247     identifier
248     @param[in] status_arg                             member Recovery status
249     @param[in] member_version_arg                     member version
250     @param[in] gtid_assignment_block_size_arg         member gtid assignment
251     block size
252     @param[in] role_arg                               member role within the
253     group
254     @param[in] in_single_primary_mode                 is member in single mode
255     @param[in] has_enforces_update_everywhere_checks  has member enforce update
256     check
257     @param[in] member_weight_arg                      member_weight
258     @param[in] lower_case_table_names_arg             lower case table names
259     @param[in] default_table_encryption_arg           default table encryption
260     @param[in] recovery_endpoints_arg                 recovery endpoints
261     advertised
262    */
263   void update(const char *hostname_arg, uint port_arg, const char *uuid_arg,
264               int write_set_extraction_algorithm,
265               const std::string &gcs_member_id_arg,
266               Group_member_info::Group_member_status status_arg,
267               Member_version &member_version_arg,
268               ulonglong gtid_assignment_block_size_arg,
269               Group_member_info::Group_member_role role_arg,
270               bool in_single_primary_mode,
271               bool has_enforces_update_everywhere_checks,
272               uint member_weight_arg, uint lower_case_table_names_arg,
273               bool default_table_encryption_arg,
274               const char *recovery_endpoints_arg);
275 
276   /**
277     Update Group_member_info.
278 
279     @param other source of the copy
280     */
281   void update(Group_member_info &other);
282 
283   /**
284     @return the member hostname
285    */
286   std::string get_hostname();
287 
288   /**
289     @return the member port
290    */
291   uint get_port();
292 
293   /**
294     @return the member uuid
295    */
296   std::string get_uuid();
297 
298   /**
299     @return the member identifier in the GCS layer
300    */
301   Gcs_member_identifier get_gcs_member_id();
302 
303   /**
304     @return the member recovery status
305    */
306   Group_member_status get_recovery_status();
307 
308   /**
309     @return the member role type code.
310    */
311   Group_member_role get_role();
312 
313   /**
314     @return the member role type code in string
315    */
316   const char *get_member_role_string();
317 
318   /**
319     @return the member plugin version
320    */
321   Member_version get_member_version();
322 
323   /**
324     @return the member GTID_EXECUTED set
325    */
326   std::string get_gtid_executed();
327 
328   /**
329     @return the member GTID_PURGED set
330    */
331   std::string get_gtid_purged();
332 
333   /**
334     @return the member GTID_RETRIEVED set for the applier channel
335   */
336   std::string get_gtid_retrieved();
337 
338   /**
339     @return the member algorithm for extracting write sets
340   */
341   uint get_write_set_extraction_algorithm();
342 
343   /**
344     @return the member gtid assignment block size
345   */
346   ulonglong get_gtid_assignment_block_size();
347 
348   /**
349     @return the member configuration flags
350   */
351   uint32 get_configuration_flags();
352 
353   /**
354     Set the primary flag
355     @param in_primary_mode is the member in primary mode
356   */
357   void set_primary_mode_flag(bool in_primary_mode);
358 
359   /**
360     Set the enforces_update_everywhere_checks flag
361     @param enforce_everywhere_checks are the update everywhere checks active or
362     not
363   */
364   void set_enforces_update_everywhere_checks_flag(
365       bool enforce_everywhere_checks);
366 
367   /**
368     @return the global-variable lower case table names value
369   */
370   uint get_lower_case_table_names();
371 
372   /**
373     @return the global-variable lower case table names value
374   */
375   bool get_default_table_encryption();
376 
377   /**
378     @return the member state of system variable
379             group_replication_single_primary_mode
380   */
381   bool in_primary_mode();
382 
383   /**
384     @return the member state of system variable
385             group_replication_enforce_update_everywhere_checks
386   */
387   bool has_enforces_update_everywhere_checks();
388 
389   /**
390     Updates this object recovery status
391 
392     @param[in] new_status the status to set
393    */
394   void update_recovery_status(Group_member_status new_status);
395 
396   /**
397     Updates this object GTID sets
398 
399     @param[in] executed_gtids the status to set
400     @param[in] purged_gtids   the status to set
401     @param[in] retrieve_gtids the status to set
402    */
403   void update_gtid_sets(std::string &executed_gtids, std::string &purged_gtids,
404                         std::string &retrieve_gtids);
405 
406   /**
407     Updates this object member role.
408 
409     @param[in] new_role the role to set.
410    */
411   void set_role(Group_member_role new_role);
412 
413   /**
414     @return the member status as string.
415    */
416   static const char *get_member_status_string(Group_member_status status);
417 
418   /**
419     @return configuration flag as string
420    */
421   static const char *get_configuration_flag_string(
422       const uint32 configuation_flag);
423 
424   /**
425     @return the member configuration flags as string
426    */
427   static std::string get_configuration_flags_string(
428       const uint32 configuation_flags);
429 
430   /**
431     @return Compare two members using member version
432    */
433   static bool comparator_group_member_version(Group_member_info *m1,
434                                               Group_member_info *m2);
435 
436   /**
437     @return Compare two members using server uuid
438    */
439   static bool comparator_group_member_uuid(Group_member_info *m1,
440                                            Group_member_info *m2);
441 
442   /**
443     @return Compare two members using member weight
444     @note if the weight is same, the member is sorted in
445           lexicographical order using its uuid.
446    */
447   static bool comparator_group_member_weight(Group_member_info *m1,
448                                              Group_member_info *m2);
449 
450   /**
451     Return true if member version is higher than other member version
452    */
453   bool has_greater_version(Group_member_info *other);
454 
455   /**
456     Return true if server uuid is lower than other member server uuid
457    */
458   bool has_lower_uuid(Group_member_info *other);
459 
460   /**
461     Return true if member weight is higher than other member weight
462    */
463   bool has_greater_weight(Group_member_info *other);
464 
465   /**
466     Redefinition of operate ==, which operate upon the uuid
467    */
468   bool operator==(Group_member_info &other);
469 
470   /**
471     Sets this member as unreachable.
472    */
473   void set_unreachable();
474 
475   /**
476     Sets this member as reachable.
477    */
478   void set_reachable();
479 
480   /**
481     Return true if this has been flagged as unreachable.
482    */
483   bool is_unreachable();
484 
485   /**
486     Update this member conflict detection to true
487    */
488   void enable_conflict_detection();
489 
490   /**
491     Update this member conflict detection to false
492    */
493   void disable_conflict_detection();
494 
495   /**
496     Return true if conflict detection is enable on this member
497    */
498   bool is_conflict_detection_enabled();
499 
500   /**
501     Update member weight
502 
503     @param[in] new_member_weight  new member_weight to set
504    */
505   void set_member_weight(uint new_member_weight);
506 
507   /**
508     Return member weight
509    */
510   uint get_member_weight();
511 
512   /**
513     @return is a group action running in this member
514   */
515   bool is_group_action_running();
516 
517   /**
518     Sets if the member is currently running a group action
519     @param is_running is an action running
520   */
521   void set_is_group_action_running(bool is_running);
522 
523   /**
524     @return is a primary election running in this member
525   */
526   bool is_primary_election_running();
527 
528   /**
529     Sets if the member is currently running a primary election
530     @param is_running is an election running
531   */
532   void set_is_primary_election_running(bool is_running);
533 
534   /**
535     List of member advertised recovery endpoints
536     @return recovery endpoints
537    */
538   std::string get_recovery_endpoints();
539 
540   /**
541     Save list of member advertised recovery endpoints
542     @param endpoints list of advertised recovery endpoints
543    */
544   void set_recovery_endpoints(const char *endpoints);
545 
546  protected:
547   void encode_payload(std::vector<unsigned char> *buffer) const;
548   void decode_payload(const unsigned char *buffer, const unsigned char *);
549 
550  private:
551   /**
552     Internal method without concurrency control.
553 
554     @return the member state of system variable
555             group_replication_single_primary_mode
556   */
557   bool in_primary_mode_internal();
558 
559   /**
560     Return true if server uuid is lower than other member server uuid
561     Internal method without concurrency control.
562    */
563   bool has_lower_uuid_internal(Group_member_info *other);
564 
565   mysql_mutex_t update_lock;
566   std::string hostname;
567   uint port;
568   std::string uuid;
569   Group_member_status status;
570   Gcs_member_identifier *gcs_member_id;
571   Member_version *member_version;
572   std::string executed_gtid_set;
573   std::string purged_gtid_set;
574   std::string retrieved_gtid_set;
575   uint write_set_extraction_algorithm;
576   uint64 gtid_assignment_block_size;
577   bool unreachable;
578   Group_member_role role;
579   uint32 configuration_flags;
580   bool conflict_detection_enable;
581   uint member_weight;
582   uint lower_case_table_names;
583   bool default_table_encryption;
584   bool group_action_running;
585   bool primary_election_running;
586   std::string recovery_endpoints;
587 #ifndef DBUG_OFF
588  public:
589   bool skip_encode_default_table_encryption;
590 #endif
591   // Allow use copy constructor on unit tests.
592   PSI_mutex_key psi_mutex_key;
593 };
594 
595 /*
596   @interface Group_member_info_manager_interface
597 
598   Defines the set of operations that a Group_member_info_manager should provide.
599   This is a component that lies on top of the GCS, on the application level,
600   providing richer and relevant information to the plugin.
601  */
602 class Group_member_info_manager_interface {
603  public:
~Group_member_info_manager_interface()604   virtual ~Group_member_info_manager_interface() {}
605 
606   virtual size_t get_number_of_members() = 0;
607 
608   /**
609     Is the member present in the group info
610 
611     @param[in] uuid uuid to check
612     @return true if present, false otherwise
613   */
614   virtual bool is_member_info_present(const std::string &uuid) = 0;
615 
616   /**
617     Retrieves a registered Group member by its uuid
618 
619     @param[in] uuid uuid to retrieve
620     @return reference to a copy of Group_member_info. NULL if not managed.
621             The return value must deallocated by the caller.
622    */
623   virtual Group_member_info *get_group_member_info(const std::string &uuid) = 0;
624 
625   /**
626     Retrieves a registered Group member by an index function.
627     One is free to determine the index function. Nevertheless, it should have
628     the same result regardless of the member of the group where it is called
629 
630     @param[in] idx the index
631     @return reference to a Group_member_info. NULL if not managed
632    */
633   virtual Group_member_info *get_group_member_info_by_index(int idx) = 0;
634 
635   /**
636     Return lowest member version.
637 
638     @return group lowest version, if used at place where member can be OFFLINE
639             or in ERROR state, version 0xFFFFFF may be returned(not found)
640    */
641   virtual Member_version get_group_lowest_online_version() = 0;
642 
643   /**
644     Retrieves a registered Group member by its backbone GCS identifier
645 
646     @param[in] idx the GCS identifier
647     @return reference to a copy of Group_member_info. NULL if not managed.
648             The return value must deallocated by the caller.
649    */
650   virtual Group_member_info *get_group_member_info_by_member_id(
651       Gcs_member_identifier idx) = 0;
652 
653   /**
654     Retrieves all Group members managed by this site
655 
656     @return a vector with copies to all managed Group_member_info
657    */
658   virtual std::vector<Group_member_info *> *get_all_members() = 0;
659 
660   /**
661     Retrieves all ONLINE Group members managed by this site, or
662     NULL if any group member version is from a version lower than
663     #TRANSACTION_WITH_GUARANTEES_VERSION.
664 
665     @return  list of all ONLINE members, if all members have version
666              equal or greater than #TRANSACTION_WITH_GUARANTEES_VERSION
667              otherwise  NULL
668 
669     @note the memory allocated for the list ownership belongs to the
670           caller
671    */
672   virtual std::list<Gcs_member_identifier> *get_online_members_with_guarantees(
673       const Gcs_member_identifier &exclude_member) = 0;
674 
675   /**
676     Adds a new member to be managed by this Group manager
677 
678     @param[in] new_member new group member
679    */
680   virtual void add(Group_member_info *new_member) = 0;
681 
682   /**
683     Removes all members of the group and update new local member.
684 
685     @param[in] update_local_member new Group member
686    */
687   virtual void update(Group_member_info *update_local_member) = 0;
688 
689   /**
690     Updates all members of the group. Typically used after a view change.
691 
692     @param[in] new_members new Group members
693    */
694   virtual void update(std::vector<Group_member_info *> *new_members) = 0;
695 
696   /**
697     Updates the status of a single member
698 
699     @param[in] uuid        member uuid
700     @param[in] new_status  status to change to
701     @param[in,out] ctx     The notification context to update.
702    */
703   virtual void update_member_status(
704       const std::string &uuid,
705       Group_member_info::Group_member_status new_status,
706       Notification_context &ctx) = 0;
707 
708   /**
709     Updates the GTID sets on a single member
710 
711 
712     @param[in] uuid            member uuid
713     @param[in] gtid_executed   the member executed GTID set
714     @param[in] purged_gtids    the server purged GTID set
715     @param[in] gtid_retrieved  the member retrieved GTID set for the applier
716   */
717   virtual void update_gtid_sets(const std::string &uuid,
718                                 std::string &gtid_executed,
719                                 std::string &purged_gtids,
720                                 std::string &gtid_retrieved) = 0;
721   /**
722     Updates the role of a single member
723 
724     @param[in] uuid        member uuid
725     @param[in] new_role    role to change to
726     @param[in,out] ctx     The notification context to update.
727    */
728   virtual void update_member_role(const std::string &uuid,
729                                   Group_member_info::Group_member_role new_role,
730                                   Notification_context &ctx) = 0;
731 
732   /**
733    Updates the primary/secondary roles of the group.
734    This method allows for all roles to be updated at once in the same method
735 
736    @param[in] uuid        the primary member uuid
737    @param[in,out] ctx     The notification context to update.
738   */
739   virtual void update_group_primary_roles(const std::string &uuid,
740                                           Notification_context &ctx) = 0;
741 
742   /**
743   Updates the weight of a single member
744 
745   @param[in] uuid        member uuid
746   @param[in] member_weight  the new weight
747 */
748   virtual void update_member_weight(const std::string &uuid,
749                                     uint member_weight) = 0;
750 
751   /**
752     Changes the primary flag on all members
753     @param in_primary_mode is the member in primary mode
754   */
755   virtual void update_primary_member_flag(bool in_primary_mode) = 0;
756 
757   /**
758     Set the enforces_update_everywhere_checks flag on all members
759     @param enforce_everywhere are the update everywhere checks active or not
760   */
761   virtual void update_enforce_everywhere_checks_flag(
762       bool enforce_everywhere) = 0;
763 
764   /**
765     Encodes this object to send via the network
766 
767     @param[out] to_encode out parameter to receive the encoded data
768    */
769   virtual void encode(std::vector<uchar> *to_encode) = 0;
770 
771   /**
772     Decodes the raw format of this object
773 
774     @param[in] to_decode raw encoded data
775     @param[in] length    raw encoded data length
776     @return a vector of Group_member_info references
777    */
778   virtual std::vector<Group_member_info *> *decode(const uchar *to_decode,
779                                                    size_t length) = 0;
780 
781   /**
782     Check if some member of the group has the conflict detection enable
783 
784     @return true if at least one member has  conflict detection enabled
785   */
786   virtual bool is_conflict_detection_enabled() = 0;
787 
788   /**
789     Return the uuid for the for the primary
790 
791     @param[out] primary_member_uuid the uuid of the primary will be assigned
792     here.
793 
794     @note If there is no primary or the member is on error state, the returned
795     uuid is "UNDEFINED". If not on primary mode it returns an empty string.
796 
797     @return true if the member is in primary mode, false if it is not.
798   */
799   virtual bool get_primary_member_uuid(std::string &primary_member_uuid) = 0;
800 
801   /**
802     Return the group member info for the current group primary
803 
804     @note the returned reference must be deallocated by the caller.
805 
806     @return reference to a Group_member_info. NULL if not managed
807   */
808   virtual Group_member_info *get_primary_member_info() = 0;
809 
810   /**
811     Check if majority of the group is unreachable
812 
813     This approach is optimistic, right after return the majority can be
814     reestablish or go away.
815 
816     @return true if majority of the group is unreachable
817   */
818   virtual bool is_majority_unreachable() = 0;
819 
820   /**
821     Check if an unreachable member exists
822 
823     This approach is optimistic, right after return a member can be marked as
824     rechable/unreachable
825 
826     @return true if an unreachable member exists
827   */
828   virtual bool is_unreachable_member_present() = 0;
829 
830   /**
831     Check if a member in recovery exists in the group
832 
833     This approach is optimistic, right after return a member can enter the group
834 
835     @return true if a member in recovery exists
836   */
837   virtual bool is_recovering_member_present() = 0;
838 
839   /**
840     This method returns all ONLINE and RECOVERING members comma separated
841     host and port in string format.
842 
843     @return hosts and port of all ONLINE and RECOVERING members
844   */
845   virtual std::string get_string_current_view_active_hosts() const = 0;
846 
847   /**
848     This method returns the update lock for consistent read of member state.
849 
850     @return update_lock reference
851   */
852   virtual mysql_mutex_t *get_update_lock() = 0;
853 };
854 
855 /**
856   @class Group_member_info_manager
857 
858   Implementation of the interface Group_member_info_manager_interface
859  */
860 class Group_member_info_manager : public Group_member_info_manager_interface {
861  public:
862   Group_member_info_manager(
863       Group_member_info *local_member_info,
864       PSI_mutex_key psi_mutex_key =
865           key_GR_LOCK_group_member_info_manager_update_lock);
866 
867   virtual ~Group_member_info_manager();
868 
869   size_t get_number_of_members();
870 
871   bool is_member_info_present(const std::string &uuid);
872 
873   Group_member_info *get_group_member_info(const std::string &uuid);
874 
875   Group_member_info *get_group_member_info_by_index(int idx);
876 
877   Member_version get_group_lowest_online_version();
878 
879   Group_member_info *get_group_member_info_by_member_id(
880       Gcs_member_identifier idx);
881 
882   std::vector<Group_member_info *> *get_all_members();
883 
884   std::list<Gcs_member_identifier> *get_online_members_with_guarantees(
885       const Gcs_member_identifier &exclude_member);
886 
887   void add(Group_member_info *new_member);
888 
889   void update(Group_member_info *update_local_member);
890 
891   void update(std::vector<Group_member_info *> *new_members);
892 
893   void update_member_status(const std::string &uuid,
894                             Group_member_info::Group_member_status new_status,
895                             Notification_context &ctx);
896 
897   void update_gtid_sets(const std::string &uuid, std::string &gtid_executed,
898                         std::string &purged_gtids, std::string &gtid_retrieved);
899 
900   void update_member_role(const std::string &uuid,
901                           Group_member_info::Group_member_role new_role,
902                           Notification_context &ctx);
903 
904   void update_group_primary_roles(const std::string &uuid,
905                                   Notification_context &ctx);
906 
907   void update_member_weight(const std::string &uuid, uint member_weight);
908 
909   void update_primary_member_flag(bool in_primary_mode);
910 
911   void update_enforce_everywhere_checks_flag(bool enforce_everywhere);
912 
913   void encode(std::vector<uchar> *to_encode);
914 
915   std::vector<Group_member_info *> *decode(const uchar *to_decode,
916                                            size_t length);
917 
918   bool is_conflict_detection_enabled();
919 
920   bool get_primary_member_uuid(std::string &primary_member_uuid);
921 
922   Group_member_info *get_primary_member_info();
923 
924   bool is_majority_unreachable();
925 
926   bool is_unreachable_member_present();
927 
928   bool is_recovering_member_present();
929 
930   std::string get_string_current_view_active_hosts() const;
931 
get_update_lock()932   mysql_mutex_t *get_update_lock() { return &update_lock; }
933 
934  private:
935   void clear_members();
936 
937   std::map<std::string, Group_member_info *> *members;
938   Group_member_info *local_member_info;
939 
940   mysql_mutex_t update_lock;
941 };
942 
943 /**
944  This is the Group_member_info_manager message.
945  It is composed by a fixed header and 1 or more Group_member_info messages.
946  Each Group_member_info message does have its own fixed header.
947 
948  The on-the-wire representation of the message is:
949 
950   +-------------------+-----------+--------------------------------------+
951   | field             | wire size | description                          |
952   +===================+===========+======================================+
953   | version           |   4 bytes | protocol version                     |
954   | fixed_hdr_len     |   2 bytes | length of the fixed header           |
955   | message_len       |   8 bytes | length of the message                |
956   | cargo_type        |   2 bytes | the cargo type in the payload        |
957   +-------------------+-----------+--------------------------------------+
958   | payload_item_type |   2 bytes | PIT_MEMBERS_NUMBER                   |
959   | payload_item_len  |   8 bytes | size of PIT_MEMBERS_NUMBER value     |
960   | payload_item      |   X bytes | number of members                    |
961   +-------------------+-----------+--------------------------------------+
962   | payload_item_type |   2 bytes | PIT_MEMBER_DATA                      |
963   | payload_item_len  |   8 bytes | size of CT_MEMBER_INFO_MESSAGE data  |
964   | payload_item      |   X bytes | CT_MEMBER_INFO_MESSAGE data          |
965   +-------------------+-----------+--------------------------------------+
966 
967  The last tree lines occur the number of times specified on
968  PIT_MEMBERS_NUMBER.
969 */
970 class Group_member_info_manager_message : public Plugin_gcs_message {
971  public:
972   enum enum_payload_item_type {
973     // This type should not be used anywhere.
974     PIT_UNKNOWN = 0,
975 
976     // Length of the payload item: 2 bytes
977     PIT_MEMBERS_NUMBER = 1,
978 
979     // Length of the payload item: variable
980     PIT_MEMBER_DATA = 2,
981 
982     // No valid type codes can appear after this one.
983     PIT_MAX = 3
984   };
985 
986   /**
987     Group_member_info_manager_message constructor.
988    */
989   Group_member_info_manager_message();
990 
991   /**
992     Group_member_info_manager_message constructor.
993 
994     @param[in] group_info  Group_member_info_manager members information
995    */
996   Group_member_info_manager_message(Group_member_info_manager &group_info);
997 
998   /**
999     Group_member_info_manager_message constructor.
1000 
1001     @param[in] member_info  Group_member_info one member information
1002    */
1003   Group_member_info_manager_message(Group_member_info *member_info);
1004 
1005   /**
1006     Group_member_info_manager_message destructor.
1007    */
1008   virtual ~Group_member_info_manager_message();
1009 
1010   /**
1011     Retrieves all Group members on this message.
1012 
1013     @return a vector with copies to all members.
1014    */
1015   std::vector<Group_member_info *> *get_all_members();
1016 
1017  protected:
1018   void encode_payload(std::vector<unsigned char> *buffer) const;
1019   void decode_payload(const unsigned char *buffer, const unsigned char *end);
1020 
1021  private:
1022   /**
1023     Clear members and its allocated memory.
1024   */
1025   void clear_members();
1026 
1027   std::vector<Group_member_info *> *members;
1028 };
1029 
1030 #endif /* MEMBER_INFO_INCLUDE */
1031