MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rpl_gtid_cache.cc
1 /* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or
4  modify it under the terms of the GNU General Public License as
5  published by the Free Software Foundation; version 2 of the
6  License.
7 
8  This program is distributed in the hope that it will be useful, but
9  WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16  02110-1301 USA */
17 
18 #include "rpl_gtid.h"
19 #include "sql_class.h"
20 #include "binlog.h"
21 
22 
24 {
25  DBUG_ENTER("Group_cache::Group_cache");
26  my_init_dynamic_array(&groups, sizeof(Cached_group), 8, 8);
27  DBUG_VOID_RETURN;
28 }
29 
30 
32 {
33  DBUG_ENTER("Group_cache::~Group_cache");
34  delete_dynamic(&groups);
35  DBUG_VOID_RETURN;
36 }
37 
38 
40 {
41  DBUG_ENTER("Group_cache::clear");
42  groups.elements= 0;
43  DBUG_VOID_RETURN;
44 }
45 
46 
48 Group_cache::add_logged_group(const THD *thd, my_off_t binlog_offset)
49 {
50  DBUG_ENTER("Group_cache::add_logged_group(THD *, my_off_t)");
51  const Gtid_specification &spec= thd->variables.gtid_next;
52  DBUG_ASSERT(spec.type != UNDEFINED_GROUP);
53  // merge with previous group if possible
54  Cached_group *prev= get_last_group();
55  if (prev != NULL && prev->spec.equals(spec))
56  DBUG_RETURN(EXTEND_EXISTING_GROUP);
57  // otherwise add a new group
58  Cached_group *group= allocate_group();
59  if (group == NULL)
60  DBUG_RETURN(ERROR);
61  group->spec= spec;
62  group->binlog_offset= binlog_offset;
63  // Update the internal status of this Group_cache (see comment above
64  // definition of enum_group_cache_type).
65  if (group->spec.type == GTID_GROUP)
66  {
67  /*
68  @todo: currently group_is_logged() requires a linear scan
69  through the cache. if this becomes a performance problem, we can
70  add a Gtid_set Group_cache::logged_groups and add logged groups
71  to it here. /Sven
72  */
73  }
74  DBUG_RETURN(APPEND_NEW_GROUP);
75 }
76 
77 
78 bool Group_cache::contains_gtid(const Gtid &gtid) const
79 {
80  int n_groups= get_n_groups();
81  for (int i= 0; i < n_groups; i++)
82  {
83  const Cached_group *group= get_unsafe_pointer(i);
84  if (group->spec.equals(gtid))
85  return true;
86  }
87  return false;
88 }
89 
90 
91 /*
92  Apparently this code is not being called. We need to
93  investigate if this is a bug or this code is not
94  necessary. /Alfranio
95 */
96 #ifdef NON_ERROR_GTID
98 Group_cache::add_empty_group(const Gtid &gtid)
99 {
100  DBUG_ENTER("Group_cache::add_empty_group");
101  // merge with previous group if possible
102  Cached_group *prev= get_last_group();
103  if (prev != NULL && prev->spec.equals(gtid))
104  DBUG_RETURN(EXTEND_EXISTING_GROUP);
105  // otherwise add new group
106  Cached_group *group= allocate_group();
107  if (group == NULL)
108  DBUG_RETURN(ERROR);
109  group->spec.type= GTID_GROUP;
110  group->spec.gtid= gtid;
111  group->binlog_offset= prev != NULL ? prev->binlog_offset : 0;
112  // Update the internal status of this Group_cache (see comment above
113  // definition of enum_group_cache_type).
114  if (group->spec.type == GTID_GROUP)
115  {
116  /*
117  @todo: currently group_is_logged() requires a linear scan
118  through the cache. if this becomes a performance problem, we can
119  add a Gtid_set Group_cache::logged_groups and add logged groups
120  to it here. /Sven
121  */
122  }
123  DBUG_RETURN(APPEND_NEW_GROUP);
124 }
125 #endif
126 
127 
128 enum_return_status Group_cache::generate_automatic_gno(THD *thd)
129 {
130  DBUG_ENTER("Group_cache::generate_automatic_gno");
131  DBUG_ASSERT(thd->variables.gtid_next.type == AUTOMATIC_GROUP);
132  DBUG_ASSERT(thd->variables.gtid_next_list.get_gtid_set() == NULL);
133  int n_groups= get_n_groups();
134  enum_group_type automatic_type= INVALID_GROUP;
135  Gtid automatic_gtid= { 0, 0 };
136  for (int i= 0; i < n_groups; i++)
137  {
139  if (group->spec.type == AUTOMATIC_GROUP)
140  {
141  if (automatic_type == INVALID_GROUP)
142  {
143  if (gtid_mode <= 1)
144  {
145  automatic_type= ANONYMOUS_GROUP;
146  }
147  else
148  {
149  automatic_type= GTID_GROUP;
150  automatic_gtid.sidno= gtid_state->get_server_sidno();
151  gtid_state->lock_sidno(automatic_gtid.sidno);
152  automatic_gtid.gno=
153  gtid_state->get_automatic_gno(automatic_gtid.sidno);
154  if (automatic_gtid.gno == -1)
155  {
156  gtid_state->unlock_sidno(automatic_gtid.sidno);
157  RETURN_REPORTED_ERROR;
158  }
159  gtid_state->acquire_ownership(thd, automatic_gtid);
160  gtid_state->unlock_sidno(automatic_gtid.sidno);
161  }
162  }
163  group->spec.type= automatic_type;
164  group->spec.gtid= automatic_gtid;
165  }
166  }
167  RETURN_OK;
168 }
169 
170 
171 enum_return_status Group_cache::get_gtids(Gtid_set *gs) const
172 {
173  DBUG_ENTER("Group_cache::get_groups");
174  int n_groups= get_n_groups();
175  PROPAGATE_REPORTED_ERROR(gs->ensure_sidno(gs->get_sid_map()->get_max_sidno()));
176  for (int i= 0; i < n_groups; i++)
177  {
179  /*
180  Cached groups only have GTIDs if SET @@SESSION.GTID_NEXT statement
181  was executed before group.
182  */
183  if (group->spec.type == GTID_GROUP)
184  PROPAGATE_REPORTED_ERROR(gs->_add_gtid(group->spec.gtid));
185  }
186  RETURN_OK;
187 }