1 /* Copyright (c) 2013, 2021, Oracle and/or its affiliates.
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 #include "pipeline_factory.h"
24 #include "handlers/event_cataloger.h"
25 #include "handlers/certification_handler.h"
26 #include "handlers/applier_handler.h"
27 #include "plugin_log.h"
28
29
get_pipeline(Handler_pipeline_type pipeline_type,Event_handler ** pipeline)30 int get_pipeline(Handler_pipeline_type pipeline_type,
31 Event_handler** pipeline)
32 {
33 DBUG_ENTER("get_pipeline(pipeline_type, pipeline)");
34
35 Handler_id* handler_list= NULL;
36 int num_handlers= get_pipeline_configuration(pipeline_type, &handler_list);
37 int error= configure_pipeline(pipeline, handler_list, num_handlers);
38 if(handler_list != NULL)
39 {
40 delete[] handler_list;
41 }
42 //when there are no handlers, the pipeline is not valid
43 DBUG_RETURN(error || num_handlers == 0);
44 }
45
get_pipeline_configuration(Handler_pipeline_type pipeline_type,Handler_id ** pipeline_conf)46 int get_pipeline_configuration(Handler_pipeline_type pipeline_type,
47 Handler_id** pipeline_conf)
48 {
49 DBUG_ENTER("get_pipeline_configuration");
50 /*
51 When a new pipeline is defined the developer shall define here what are
52 the handlers that belong to it and their order.
53 */
54 switch (pipeline_type)
55 {
56 case STANDARD_GROUP_REPLICATION_PIPELINE:
57 (*pipeline_conf)= new Handler_id[3];
58 (*pipeline_conf)[0]= CATALOGING_HANDLER;
59 (*pipeline_conf)[1]= CERTIFICATION_HANDLER;
60 (*pipeline_conf)[2]= SQL_THREAD_APPLICATION_HANDLER;
61 DBUG_RETURN(3);
62 default:
63 log_message(MY_ERROR_LEVEL, "Unknown group replication applier pipeline"
64 " requested"); /* purecov: inspected */
65 }
66 DBUG_RETURN(0); /* purecov: inspected */
67 }
68
configure_pipeline(Event_handler ** pipeline,Handler_id handler_list[],int num_handlers)69 int configure_pipeline(Event_handler** pipeline, Handler_id handler_list[],
70 int num_handlers)
71 {
72 DBUG_ENTER("configure_pipeline(pipeline, handler_list[], num_handlers)");
73 int error= 0;
74
75 for (int i= 0; i < num_handlers; ++i)
76 {
77 Event_handler* handler= NULL;
78
79 /*
80 When a new handler is define the developer shall insert it here
81 */
82 switch (handler_list[i])
83 {
84 case CATALOGING_HANDLER:
85 handler= new Event_cataloger();
86 break;
87 case CERTIFICATION_HANDLER:
88 handler= new Certification_handler();
89 break;
90 case SQL_THREAD_APPLICATION_HANDLER:
91 handler= new Applier_handler();
92 break;
93 default:
94 error= 1; /* purecov: inspected */
95 log_message(MY_ERROR_LEVEL,
96 "Unable to bootstrap group replication event handling "
97 "infrastructure. Unknown handler type: %d",
98 handler_list[i]); /* purecov: inspected */
99 }
100
101 if (!handler)
102 {
103 /* purecov: begin inspected */
104 if (!error) //not an unknown handler but a initialization error
105 {
106 log_message(MY_ERROR_LEVEL,
107 "One of the group replication applier handlers is null due"
108 " to an initialization error");
109 }
110 DBUG_RETURN(1);
111 /* purecov: end */
112 }
113
114 /*
115 TODO: This kind of tests don't belong here. We need a way to
116 do this in a static way before initialization.
117 */
118 //Record the handler role if unique
119 if (handler->is_unique())
120 {
121 for (int z= 0; z < i; ++z)
122 {
123 DBUG_EXECUTE_IF("double_unique_handler",
124 handler_list[z]= handler_list[i];);
125
126 //Check to see if the handler was already used in this pipeline
127 if (handler_list[i] == handler_list[z])
128 {
129 log_message(MY_ERROR_LEVEL,
130 "A group replication applier handler, marked as unique,"
131 " is already in use.");
132 delete handler;
133 DBUG_RETURN(1);
134 }
135
136 //check to see if no other handler has the same role
137 Event_handler *handler_with_same_role= NULL;
138 Event_handler::get_handler_by_role(*pipeline,handler->get_role(),
139 &handler_with_same_role);
140 if (handler_with_same_role != NULL)
141 {
142 /* purecov: begin inspected */
143 log_message(MY_ERROR_LEVEL,
144 "A group replication applier handler role, "
145 "that was marked as unique, is already in use.");
146 delete handler;
147 DBUG_RETURN(1);
148 /* purecov: end */
149 }
150
151 }
152 }
153
154 if ((error= handler->initialize()))
155 {
156 /* purecov: begin inspected */
157 log_message(MY_ERROR_LEVEL, "Error on group replication applier "
158 "handler initialization");
159 DBUG_RETURN(error);
160 /* purecov: end */
161 }
162
163 //Add the handler to the pipeline
164 Event_handler::append_handler(pipeline,handler);
165 }
166 DBUG_RETURN(0);
167 }
168