1 /*
2 Copyright (c) 2011, 2021, Oracle and/or its affiliates.
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 #ifndef NDB_SHARE_H
26 #define NDB_SHARE_H
27
28 #include <my_global.h>
29 #include <my_alloc.h> // MEM_ROOT
30 #include <thr_lock.h> // THR_LOCK
31 #include <my_bitmap.h> // MY_BITMAP
32
33 #include <ndbapi/Ndb.hpp> // Ndb::TupleIdRange
34
35 enum NDB_SHARE_STATE {
36 NSS_INITIAL= 0,
37 NSS_DROPPED,
38 NSS_ALTERED
39 };
40
41 #ifdef HAVE_NDB_BINLOG
42 enum Ndb_binlog_type
43 {
44 NBT_DEFAULT = 0
45 ,NBT_NO_LOGGING = 1
46 ,NBT_UPDATED_ONLY = 2
47 ,NBT_FULL = 3
48 ,NBT_USE_UPDATE = 4
49 ,NBT_UPDATED_ONLY_USE_UPDATE = 6
50 ,NBT_FULL_USE_UPDATE = 7
51 ,NBT_UPDATED_ONLY_MINIMAL = 8
52 ,NBT_UPDATED_FULL_MINIMAL = 9
53 };
54 #endif
55
56
57 /*
58 Stats that can be retrieved from ndb
59 */
60 struct Ndb_statistics {
61 Uint64 row_count;
62 Uint64 commit_count;
63 ulong row_size;
64 Uint64 fragment_memory;
65 Uint64 fragment_extent_space;
66 Uint64 fragment_extent_free_space;
67 };
68
69
70 struct NDB_SHARE {
71 NDB_SHARE_STATE state;
72 THR_LOCK lock;
73 native_mutex_t mutex;
74 struct NDB_SHARE_KEY* key;
75 uint use_count;
76 uint commit_count_lock;
77 ulonglong commit_count;
78 char *db;
79 char *table_name;
80 Ndb::TupleIdRange tuple_id_range;
81 struct Ndb_statistics stat;
82 struct Ndb_index_stat* index_stat_list;
83 bool util_thread; // if opened by util thread
84 uint32 flags;
85 #ifdef HAVE_NDB_BINLOG
86 struct NDB_CONFLICT_FN_SHARE *m_cfn_share;
87 #endif
88 class Ndb_event_data *event_data; // Place holder before NdbEventOperation is created
89 class NdbEventOperation *op;
90 class NdbEventOperation *new_op;
91
92 static NDB_SHARE* create(const char* key,
93 struct TABLE* table);
94 static void destroy(NDB_SHARE* share);
95
96 class Ndb_event_data* get_event_data_ptr() const;
97
98 void print(const char* where, FILE* file = stderr) const;
99
100 /*
101 Returns true if this share need to subscribe to
102 events from the table.
103 */
104 bool need_events(bool default_on) const;
105
106 // Functions for working with the opaque NDB_SHARE_KEY
107 static struct NDB_SHARE_KEY* create_key(const char *new_key);
108 static void free_key(struct NDB_SHARE_KEY*);
109
110 static const uchar* key_get_key(struct NDB_SHARE_KEY*);
111 static size_t key_get_length(struct NDB_SHARE_KEY*);
112 static char* key_get_db_name(struct NDB_SHARE_KEY*);
113 static char* key_get_table_name(struct NDB_SHARE_KEY*);
114
115 size_t key_length() const;
116 const char* key_string() const;
117
118 };
119
120
121 inline
122 NDB_SHARE_STATE
get_ndb_share_state(NDB_SHARE * share)123 get_ndb_share_state(NDB_SHARE *share)
124 {
125 NDB_SHARE_STATE state;
126 native_mutex_lock(&share->mutex);
127 state= share->state;
128 native_mutex_unlock(&share->mutex);
129 return state;
130 }
131
132
133 inline
134 void
set_ndb_share_state(NDB_SHARE * share,NDB_SHARE_STATE state)135 set_ndb_share_state(NDB_SHARE *share, NDB_SHARE_STATE state)
136 {
137 native_mutex_lock(&share->mutex);
138 share->state= state;
139 native_mutex_unlock(&share->mutex);
140 }
141
142
143 /* NDB_SHARE.flags */
144 #define NSF_HIDDEN_PK 1u /* table has hidden primary key */
145 #define NSF_BLOB_FLAG 2u /* table has blob attributes */
146 #define NSF_NO_BINLOG 4u /* table should not be binlogged */
147 #define NSF_BINLOG_FULL 8u /* table should be binlogged with full rows */
148 #define NSF_BINLOG_USE_UPDATE 16u /* table update should be binlogged using
149 update log event */
150 #define NSF_BINLOG_MINIMAL_UPDATE 32u /* table update should be binlogged using
151 minimal format: before(PK):after(changed cols) */
set_binlog_logging(NDB_SHARE * share)152 inline void set_binlog_logging(NDB_SHARE *share)
153 {
154 DBUG_PRINT("info", ("set_binlog_logging"));
155 share->flags&= ~NSF_NO_BINLOG;
156 }
set_binlog_nologging(NDB_SHARE * share)157 inline void set_binlog_nologging(NDB_SHARE *share)
158 {
159 DBUG_PRINT("info", ("set_binlog_nologging"));
160 share->flags|= NSF_NO_BINLOG;
161 }
get_binlog_nologging(NDB_SHARE * share)162 inline my_bool get_binlog_nologging(NDB_SHARE *share)
163 { return (share->flags & NSF_NO_BINLOG) != 0; }
set_binlog_updated_only(NDB_SHARE * share)164 inline void set_binlog_updated_only(NDB_SHARE *share)
165 {
166 DBUG_PRINT("info", ("set_binlog_updated_only"));
167 share->flags&= ~NSF_BINLOG_FULL;
168 }
set_binlog_full(NDB_SHARE * share)169 inline void set_binlog_full(NDB_SHARE *share)
170 {
171 DBUG_PRINT("info", ("set_binlog_full"));
172 share->flags|= NSF_BINLOG_FULL;
173 }
get_binlog_full(NDB_SHARE * share)174 inline my_bool get_binlog_full(NDB_SHARE *share)
175 { return (share->flags & NSF_BINLOG_FULL) != 0; }
set_binlog_use_write(NDB_SHARE * share)176 inline void set_binlog_use_write(NDB_SHARE *share)
177 {
178 DBUG_PRINT("info", ("set_binlog_use_write"));
179 share->flags&= ~NSF_BINLOG_USE_UPDATE;
180 }
set_binlog_use_update(NDB_SHARE * share)181 inline void set_binlog_use_update(NDB_SHARE *share)
182 {
183 DBUG_PRINT("info", ("set_binlog_use_update"));
184 share->flags|= NSF_BINLOG_USE_UPDATE;
185 }
get_binlog_use_update(NDB_SHARE * share)186 inline my_bool get_binlog_use_update(NDB_SHARE *share)
187 { return (share->flags & NSF_BINLOG_USE_UPDATE) != 0; }
188
set_binlog_update_minimal(NDB_SHARE * share)189 static inline void set_binlog_update_minimal(NDB_SHARE *share)
190 {
191 DBUG_PRINT("info", ("set_binlog_update_minimal"));
192 share->flags|= NSF_BINLOG_MINIMAL_UPDATE;
193 }
194
get_binlog_update_minimal(const NDB_SHARE * share)195 static inline bool get_binlog_update_minimal(const NDB_SHARE *share)
196 {
197 return (share->flags & NSF_BINLOG_MINIMAL_UPDATE) != 0;
198 }
199
200 NDB_SHARE *ndbcluster_get_share(const char *key,
201 struct TABLE *table,
202 bool create_if_not_exists,
203 bool have_lock);
204 NDB_SHARE *ndbcluster_get_share(NDB_SHARE *share);
205 void ndbcluster_free_share(NDB_SHARE **share, bool have_lock);
206 void ndbcluster_real_free_share(NDB_SHARE **share);
207 int handle_trailing_share(THD *thd, NDB_SHARE *share);
208 int ndbcluster_rename_share(THD *thd,
209 NDB_SHARE *share,
210 struct NDB_SHARE_KEY* new_key);
211 void ndbcluster_mark_share_dropped(NDB_SHARE*);
212 inline NDB_SHARE *get_share(const char *key,
213 struct TABLE *table,
214 bool create_if_not_exists= TRUE,
215 bool have_lock= FALSE)
216 {
217 return ndbcluster_get_share(key, table, create_if_not_exists, have_lock);
218 }
219
get_share(NDB_SHARE * share)220 inline NDB_SHARE *get_share(NDB_SHARE *share)
221 {
222 return ndbcluster_get_share(share);
223 }
224
225 inline void free_share(NDB_SHARE **share, bool have_lock= FALSE)
226 {
227 ndbcluster_free_share(share, have_lock);
228 }
229
230 /**
231 @brief Utility class for working with a temporary
232 NDB_SHARE* references RAII style
233
234 The class will automatically "get" a NDB_SHARE*
235 reference and release it when going out of scope.
236 */
237 class Ndb_share_temp_ref {
238 NDB_SHARE* m_share;
239
240 Ndb_share_temp_ref(const Ndb_share_temp_ref&); // prevent
241 Ndb_share_temp_ref& operator=(const Ndb_share_temp_ref&); // prevent
242 public:
Ndb_share_temp_ref(const char * key)243 Ndb_share_temp_ref(const char* key)
244 {
245 m_share= get_share(key, NULL, FALSE);
246 // Should always exist
247 assert(m_share);
248 // already existed + this temp ref
249 assert(m_share->use_count >= 2);
250
251 DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u",
252 m_share->key_string(), m_share->use_count));
253 }
254
~Ndb_share_temp_ref()255 ~Ndb_share_temp_ref()
256 {
257 /* release the temporary reference */
258 assert(m_share);
259 // at least this temp ref
260 assert(m_share->use_count > 0);
261
262 /* ndb_share reference temporary free */
263 DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u",
264 m_share->key_string(), m_share->use_count));
265
266 free_share(&m_share);
267 }
268
269 // Return the NDB_SHARE* by type conversion operator
270 operator NDB_SHARE*() const
271 {
272 assert(m_share);
273 return m_share;
274 }
275
276 // Return the NDB_SHARE* when using pointer operator
277 const NDB_SHARE* operator->() const
278 {
279 assert(m_share);
280 return m_share;
281 }
282 };
283
284
285 #define dbug_print_share(t, s) \
286 DBUG_LOCK_FILE; \
287 DBUG_EXECUTE("info", \
288 (s)->print((t), DBUG_FILE);); \
289 DBUG_UNLOCK_FILE;
290
291 #endif
292