1 /* Copyright (c) 2018, 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 "gcs_view_modification_notifier.h"
24 #include "plugin_psi.h"
25 
26 
Plugin_gcs_view_modification_notifier()27 Plugin_gcs_view_modification_notifier::Plugin_gcs_view_modification_notifier()
28   :view_changing(false), cancelled_view_change(false),
29    injected_view_modification(false), error(0)
30 {
31 
32   mysql_cond_init(key_GR_COND_view_modification_wait, &wait_for_view_cond);
33   mysql_mutex_init(key_GR_LOCK_view_modification_wait, &wait_for_view_mutex,
34                    MY_MUTEX_INIT_FAST);
35 }
36 
~Plugin_gcs_view_modification_notifier()37 Plugin_gcs_view_modification_notifier::~Plugin_gcs_view_modification_notifier()
38 {
39   mysql_mutex_destroy(&wait_for_view_mutex);
40   mysql_cond_destroy(&wait_for_view_cond);
41 }
42 
43 void
start_view_modification()44 Plugin_gcs_view_modification_notifier::start_view_modification()
45 {
46   mysql_mutex_lock(&wait_for_view_mutex);
47   view_changing= true;
48   cancelled_view_change= false;
49   injected_view_modification= false;
50   error= 0;
51   mysql_mutex_unlock(&wait_for_view_mutex);
52 }
53 
54 void
start_injected_view_modification()55 Plugin_gcs_view_modification_notifier::start_injected_view_modification()
56 {
57   mysql_mutex_lock(&wait_for_view_mutex);
58   view_changing= true;
59   cancelled_view_change= false;
60   injected_view_modification= true;
61   error= 0;
62   mysql_mutex_unlock(&wait_for_view_mutex);
63 }
64 
65 bool
is_injected_view_modification()66 Plugin_gcs_view_modification_notifier::is_injected_view_modification()
67 {
68   mysql_mutex_lock(&wait_for_view_mutex);
69   bool result= injected_view_modification;
70   mysql_mutex_unlock(&wait_for_view_mutex);
71   return result;
72 }
73 
74 bool
is_view_modification_ongoing()75 Plugin_gcs_view_modification_notifier::is_view_modification_ongoing()
76 {
77   mysql_mutex_lock(&wait_for_view_mutex);
78   bool result = view_changing;
79   mysql_mutex_unlock(&wait_for_view_mutex);
80   return result;
81 }
82 
83 void
end_view_modification()84 Plugin_gcs_view_modification_notifier::end_view_modification()
85 {
86   mysql_mutex_lock(&wait_for_view_mutex);
87   view_changing= false;
88   mysql_cond_broadcast(&wait_for_view_cond);
89   mysql_mutex_unlock(&wait_for_view_mutex);
90 }
91 
92 void
cancel_view_modification(int error)93 Plugin_gcs_view_modification_notifier::cancel_view_modification(int error)
94 {
95   mysql_mutex_lock(&wait_for_view_mutex);
96   view_changing= false;
97   cancelled_view_change= true;
98   this->error= error;
99   mysql_cond_broadcast(&wait_for_view_cond);
100   mysql_mutex_unlock(&wait_for_view_mutex);
101 }
102 
103 bool
is_cancelled()104 Plugin_gcs_view_modification_notifier::is_cancelled()
105 {
106   assert(view_changing == false);
107   return cancelled_view_change;
108 }
109 
110 bool
wait_for_view_modification(long timeout)111 Plugin_gcs_view_modification_notifier::wait_for_view_modification(long timeout)
112 {
113   struct timespec ts;
114   int result= 0;
115 
116   mysql_mutex_lock(&wait_for_view_mutex);
117 
118   DBUG_EXECUTE_IF("group_replication_skip_wait_for_view_modification",
119                   { view_changing= false; };);
120 
121   while (view_changing && !cancelled_view_change)
122   {
123     set_timespec(&ts, timeout);
124     result=
125          mysql_cond_timedwait(&wait_for_view_cond, &wait_for_view_mutex, &ts);
126 
127     if(result != 0) //It means that it broke by timeout or an error.
128     {
129       view_changing= false;
130       break;
131     }
132   }
133 
134   DBUG_EXECUTE_IF("group_replication_force_view_modification_timeout",
135                   { result= 1; };);
136   if (result != 0)
137     error= GROUP_REPLICATION_CONFIGURATION_ERROR;
138 
139   mysql_mutex_unlock(&wait_for_view_mutex);
140 
141   return (result != 0 || cancelled_view_change);
142 }
143 
144 int
get_error()145 Plugin_gcs_view_modification_notifier::get_error()
146 {
147   assert(view_changing == false);
148   return error;
149 }
150