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