1 /*
2 Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "ndb_share.h"
26 #include "ndb_event_data.h"
27 #include "ndb_dist_priv_util.h"
28 #include "ha_ndbcluster_tables.h"
29 #include "ndb_conflict.h"
30 #include "ndb_name_util.h"
31
32 #include <ndbapi/NdbEventOperation.hpp>
33
34 #include <my_sys.h>
35
36 extern Ndb* g_ndb;
37
38 void
destroy(NDB_SHARE * share)39 NDB_SHARE::destroy(NDB_SHARE* share)
40 {
41 thr_lock_delete(&share->lock);
42 native_mutex_destroy(&share->mutex);
43
44 #ifdef HAVE_NDB_BINLOG
45 teardown_conflict_fn(g_ndb, share->m_cfn_share);
46 #endif
47 share->new_op= 0;
48 Ndb_event_data* event_data = share->event_data;
49 if (event_data)
50 {
51 delete event_data;
52 event_data= 0;
53 }
54 // Release memory for the variable length strings held by
55 // key but also referenced by db, table_name and shadow_table->db etc.
56 free_key(share->key);
57 my_free(share);
58 }
59
60 /*
61 Struct holding dynamic length strings for NDB_SHARE. The type is
62 opaque to the user of NDB_SHARE and should
63 only be accessed using NDB_SHARE accessor functions.
64
65 All the strings are zero terminated.
66
67 Layout:
68 size_t key_length
69 "key"\0
70 "db\0"
71 "table_name\0"
72 */
73 struct NDB_SHARE_KEY {
74 size_t m_key_length;
75 char m_buffer[1];
76 };
77
78 NDB_SHARE_KEY*
create_key(const char * new_key)79 NDB_SHARE::create_key(const char *new_key)
80 {
81 const size_t new_key_length = strlen(new_key);
82
83 char db_name_buf[FN_HEADLEN];
84 ndb_set_dbname(new_key, db_name_buf);
85 const size_t db_name_len = strlen(db_name_buf);
86
87 char table_name_buf[FN_HEADLEN];
88 ndb_set_tabname(new_key, table_name_buf);
89 const size_t table_name_len = strlen(table_name_buf);
90
91 // Calculate total size needed for the variable length strings
92 const size_t size=
93 sizeof(NDB_SHARE_KEY) +
94 new_key_length +
95 db_name_len + 1 +
96 table_name_len + 1;
97
98 NDB_SHARE_KEY* allocated_key=
99 (NDB_SHARE_KEY*) my_malloc(PSI_INSTRUMENT_ME,
100 size,
101 MYF(MY_WME | ME_FATALERROR));
102
103 allocated_key->m_key_length = new_key_length;
104
105 // Copy key into the buffer
106 char* buf_ptr = allocated_key->m_buffer;
107 my_stpcpy(buf_ptr, new_key);
108 buf_ptr += new_key_length + 1;
109
110 // Copy db_name into the buffer
111 my_stpcpy(buf_ptr, db_name_buf);
112 buf_ptr += db_name_len + 1;
113
114 // Copy table_name into the buffer
115 my_stpcpy(buf_ptr, table_name_buf);
116 buf_ptr += table_name_len;
117
118 // Check that writing has not occured beyond end of allocated memory
119 assert(buf_ptr < reinterpret_cast<char*>(allocated_key) + size);
120
121 DBUG_PRINT("info", ("size: %lu, sizeof(NDB_SHARE_KEY): %lu",
122 size, sizeof(NDB_SHARE_KEY)));
123 DBUG_PRINT("info", ("new_key: '%s', %lu", new_key, new_key_length));
124 DBUG_PRINT("info", ("db_name: '%s', %lu", db_name_buf, db_name_len));
125 DBUG_PRINT("info", ("table_name: '%s', %lu", table_name_buf, table_name_len));
126 DBUG_DUMP("NDB_SHARE_KEY: ", (const uchar*)allocated_key->m_buffer, size);
127
128 return allocated_key;
129 }
130
131
free_key(NDB_SHARE_KEY * key)132 void NDB_SHARE::free_key(NDB_SHARE_KEY* key)
133 {
134 my_free(key);
135 }
136
137
key_get_key(NDB_SHARE_KEY * key)138 const uchar* NDB_SHARE::key_get_key(NDB_SHARE_KEY* key)
139 {
140 assert(key->m_key_length == strlen(key->m_buffer));
141 return (const uchar*)key->m_buffer;
142 }
143
144
key_get_length(NDB_SHARE_KEY * key)145 size_t NDB_SHARE::key_get_length(NDB_SHARE_KEY* key)
146 {
147 assert(key->m_key_length == strlen(key->m_buffer));
148 return key->m_key_length;
149 }
150
151
key_get_db_name(NDB_SHARE_KEY * key)152 char* NDB_SHARE::key_get_db_name(NDB_SHARE_KEY* key)
153 {
154 char* buf_ptr = key->m_buffer;
155 // Step past the key string and it's zero terminator
156 buf_ptr += key->m_key_length + 1;
157 return buf_ptr;
158 }
159
160
key_get_table_name(NDB_SHARE_KEY * key)161 char* NDB_SHARE::key_get_table_name(NDB_SHARE_KEY* key)
162 {
163 char* buf_ptr = key_get_db_name(key);
164 const size_t db_name_len = strlen(buf_ptr);
165 // Step past the db name string and it's zero terminator
166 buf_ptr += db_name_len + 1;
167 return buf_ptr;
168 }
169
170
key_length() const171 size_t NDB_SHARE::key_length() const
172 {
173 assert(key->m_key_length == strlen(key->m_buffer));
174 return key->m_key_length;
175 }
176
177
key_string() const178 const char* NDB_SHARE::key_string() const
179 {
180 assert(strlen(key->m_buffer) == key->m_key_length);
181 return key->m_buffer;
182 }
183
184
185 bool
need_events(bool default_on) const186 NDB_SHARE::need_events(bool default_on) const
187 {
188 DBUG_ENTER("NDB_SHARE::need_events");
189 DBUG_PRINT("enter", ("db: %s, table_name: %s",
190 db, table_name));
191
192 if (default_on)
193 {
194 // Events are on by default, check if it should be turned off
195
196 if (Ndb_dist_priv_util::is_distributed_priv_table(db, table_name))
197 {
198 /*
199 The distributed privilege tables are distributed by writing
200 the CREATE USER, GRANT, REVOKE etc. to ndb_schema -> no need
201 to listen to events from those table
202 */
203 DBUG_PRINT("exit", ("no events for dist priv table"));
204 DBUG_RETURN(false);
205 }
206
207 DBUG_PRINT("exit", ("need events(the default for this mysqld)"));
208 DBUG_RETURN(true);
209 }
210
211 // Events are off by default, check if it should be turned on
212 if (strcmp(db, NDB_REP_DB) == 0)
213 {
214 // The table is in "mysql" database
215 if (strcmp(table_name, NDB_SCHEMA_TABLE) == 0)
216 {
217 DBUG_PRINT("exit", ("need events for " NDB_SCHEMA_TABLE));
218 DBUG_RETURN(true);
219 }
220
221 if (strcmp(table_name, NDB_APPLY_TABLE) == 0)
222 {
223 DBUG_PRINT("exit", ("need events for " NDB_APPLY_TABLE));
224 DBUG_RETURN(true);
225 }
226 }
227
228 DBUG_PRINT("exit", ("no events(the default for this mysqld)"));
229 DBUG_RETURN(false);
230 }
231
232
get_event_data_ptr() const233 Ndb_event_data* NDB_SHARE::get_event_data_ptr() const
234 {
235 if (event_data)
236 {
237 // The event_data pointer is only used before
238 // creating the NdbEventoperation -> check no op yet
239 assert(!op);
240
241 return event_data;
242 }
243
244 if (op)
245 {
246 // The event_data should now be empty since it's been moved to
247 // op's custom data
248 assert(!event_data);
249
250 // Check that op has custom data
251 assert(op->getCustomData());
252
253 return (Ndb_event_data*)op->getCustomData();
254 }
255
256 return NULL;
257 }
258
259
print(const char * where,FILE * file) const260 void NDB_SHARE::print(const char* where, FILE* file) const
261 {
262 fprintf(file, "%s %s.%s: use_count: %u\n",
263 where, db, table_name, use_count);
264 fprintf(file, " - key: '%s', key_length: %lu\n",
265 key_string(), key_length());
266 fprintf(file, " - commit_count: %llu\n", commit_count);
267 if (event_data)
268 fprintf(file, " - event_data: %p\n", event_data);
269 if (op)
270 fprintf(file, " - op: %p\n", op);
271 if (new_op)
272 fprintf(file, " - new_op: %p\n", new_op);
273
274 Ndb_event_data *event_data_ptr= get_event_data_ptr();
275 if (event_data_ptr)
276 event_data_ptr->print(" -", file);
277 }
278