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