MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rpl_gtid_sid_map.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 
20 #include "hash.h"
21 #include "mysqld_error.h"
22 
23 
25  : sid_lock(_sid_lock)
26 {
27  DBUG_ENTER("Sid_map::Sid_map");
28  my_init_dynamic_array(&_sidno_to_sid, sizeof(Node *), 8, 8);
29  my_init_dynamic_array(&_sorted, sizeof(rpl_sidno), 8, 8);
30  my_hash_init(&_sid_to_sidno, &my_charset_bin, 20,
31  offsetof(Node, sid.bytes), Uuid::BYTE_LENGTH, NULL,
32  my_free, 0);
33  DBUG_VOID_RETURN;
34 }
35 
36 
38 {
39  DBUG_ENTER("Sid_map::~Sid_map");
40  delete_dynamic(&_sidno_to_sid);
41  delete_dynamic(&_sorted);
42  my_hash_free(&_sid_to_sidno);
43  DBUG_VOID_RETURN;
44 }
45 
46 
47 /*
48  This code is not being used but we will keep it as it may be
49  useful to optimize gtids by avoiding sharing mappings from
50  sid to sidno. For instance, the IO Thread and the SQL Thread
51  may have different mappings in the future.
52 */
53 #ifdef NON_DISABLED_GTID
54 enum_return_status Sid_map::clear()
55 {
56  DBUG_ENTER("Sid_map::clear");
57  my_hash_free(&_sid_to_sidno);
58  my_hash_init(&_sid_to_sidno, &my_charset_bin, 20,
59  offsetof(Node, sid.bytes), Uuid::BYTE_LENGTH, NULL,
60  my_free, 0);
61  reset_dynamic(&_sidno_to_sid);
62  reset_dynamic(&_sorted);
63  RETURN_OK;
64 }
65 #endif
66 
67 
68 rpl_sidno Sid_map::add_sid(const rpl_sid &sid)
69 {
70  DBUG_ENTER("Sid_map::add_sid(const rpl_sid *)");
71 #ifndef DBUG_OFF
72  char buf[Uuid::TEXT_LENGTH + 1];
73  sid.to_string(buf);
74  DBUG_PRINT("info", ("SID=%s", buf));
75 #endif
76  if (sid_lock)
77  sid_lock->assert_some_lock();
78  Node *node= (Node *)my_hash_search(&_sid_to_sidno, sid.bytes,
80  if (node != NULL)
81  {
82  DBUG_PRINT("info", ("existed as sidno=%d", node->sidno));
83  DBUG_RETURN(node->sidno);
84  }
85 
86  bool is_wrlock= false;
87  if (sid_lock)
88  {
89  is_wrlock= sid_lock->is_wrlock();
90  if (!is_wrlock)
91  {
92  sid_lock->unlock();
93  sid_lock->wrlock();
94  }
95  }
96  DBUG_PRINT("info", ("is_wrlock=%d sid_lock=%p", is_wrlock, sid_lock));
97  rpl_sidno sidno;
98  node= (Node *)my_hash_search(&_sid_to_sidno, sid.bytes,
100  if (node != NULL)
101  sidno= node->sidno;
102  else
103  {
104  sidno= get_max_sidno() + 1;
105  if (add_node(sidno, sid) != RETURN_STATUS_OK)
106  sidno= -1;
107  }
108 
109  if (sid_lock)
110  {
111  if (!is_wrlock)
112  {
113  sid_lock->unlock();
114  sid_lock->rdlock();
115  }
116  }
117  DBUG_RETURN(sidno);
118 }
119 
120 enum_return_status Sid_map::add_node(rpl_sidno sidno, const rpl_sid &sid)
121 {
122  DBUG_ENTER("Sid_map::add_node(rpl_sidno, const rpl_sid *)");
123  if (sid_lock)
124  sid_lock->assert_some_wrlock();
125  Node *node= (Node *)my_malloc(sizeof(Node), MYF(MY_WME));
126  if (node == NULL)
127  RETURN_REPORTED_ERROR;
128 
129  node->sidno= sidno;
130  node->sid= sid;
131  if (insert_dynamic(&_sidno_to_sid, &node) == 0)
132  {
133  if (insert_dynamic(&_sorted, &sidno) == 0)
134  {
135  if (my_hash_insert(&_sid_to_sidno, (uchar *)node) == 0)
136  {
137 #ifdef MYSQL_SERVER
138  /*
139  If this is the global_sid_map, we take the opportunity to
140  resize all arrays in gtid_state while holding the wrlock.
141  */
142  if (this != global_sid_map ||
143  gtid_state->ensure_sidno() == RETURN_STATUS_OK)
144 #endif
145  {
146  // We have added one element to the end of _sorted. Now we
147  // bubble it down to the sorted position.
148  int sorted_i= sidno - 1;
149  rpl_sidno *prev_sorted_p= dynamic_element(&_sorted, sorted_i,
150  rpl_sidno *);
151  sorted_i--;
152  while (sorted_i >= 0)
153  {
154  rpl_sidno *sorted_p= dynamic_element(&_sorted, sorted_i,
155  rpl_sidno *);
156  const rpl_sid &other_sid= sidno_to_sid(*sorted_p);
157  if (memcmp(sid.bytes, other_sid.bytes,
158  rpl_sid::BYTE_LENGTH) >= 0)
159  break;
160  memcpy(prev_sorted_p, sorted_p, sizeof(rpl_sidno));
161  sorted_i--;
162  prev_sorted_p= sorted_p;
163  }
164  memcpy(prev_sorted_p, &sidno, sizeof(rpl_sidno));
165  RETURN_OK;
166  }
167  }
168  pop_dynamic(&_sorted);
169  }
170  pop_dynamic(&_sidno_to_sid);
171  }
172  my_free(node);
173 
174  BINLOG_ERROR(("Out of memory."), (ER_OUT_OF_RESOURCES, MYF(0)));
175  RETURN_REPORTED_ERROR;
176 }