1 /*
2    Copyright (c) 2017, 2020, 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 #ifndef NDB_DD_CLIENT_H
26 #define NDB_DD_CLIENT_H
27 
28 #include <map>
29 #include <set>
30 #include <string>
31 #include <unordered_set>
32 #include <vector>
33 
34 #include "my_inttypes.h"
35 #include "sql/dd/object_id.h"
36 #include "sql/dd/string_type.h"
37 #include "sql/mdl.h"
38 
39 namespace dd {
40 typedef String_type sdi_t;
41 namespace cache {
42 class Dictionary_client;
43 }
44 class Schema;
45 class Table;
46 class Tablespace;
47 }  // namespace dd
48 
49 /*
50  * Helper class to Ndb_dd_client to fetch and
51  * invalidate tables referenced by foreign keys.
52  * Used by the schema distribution participant
53  */
54 class Ndb_referenced_tables_invalidator {
55   std::set<std::pair<std::string, std::string>> m_referenced_tables;
56   class THD *const m_thd;
57   class Ndb_dd_client &m_dd_client;
58 
59   bool add_and_lock_referenced_table(const char *schema_name,
60                                      const char *table_name);
61 
62  public:
Ndb_referenced_tables_invalidator(class THD * thd,class Ndb_dd_client & dd_client)63   Ndb_referenced_tables_invalidator(class THD *thd,
64                                     class Ndb_dd_client &dd_client)
65       : m_thd(thd), m_dd_client(dd_client) {}
66   bool fetch_referenced_tables_to_invalidate(const char *schema_name,
67                                              const char *table_name,
68                                              const dd::Table *table_def,
69                                              bool skip_ndb_dict_fetch = false);
70   bool invalidate() const;
71 };
72 
73 /*
74   Class encapculating the code for accessing the DD
75   from ndbcluster
76 
77   Handles:
78    - locking and releasing MDL(metadata locks)
79    - disabling and restoring autocommit
80    - transaction commit and rollback, will automatically
81      rollback in case commit has not been called(unless
82      auto rollback has been turned off)
83 */
84 
85 class Ndb_dd_client {
86   class THD *const m_thd;
87   dd::cache::Dictionary_client *m_client;
88   void *m_auto_releaser;  // Opaque pointer
89   // List of MDL locks taken in EXPLICIT scope by Ndb_dd_client
90   std::vector<class MDL_ticket *> m_acquired_mdl_tickets;
91   // MDL savepoint which allows releasing MDL locks taken by called
92   // functions in TRANSACTIONAL and STATEMENT scope
93   const MDL_savepoint m_save_mdl_locks;
94   ulonglong m_save_option_bits{0};
95   bool m_comitted{false};
96   bool m_auto_rollback{true};
97 
98   void disable_autocommit();
99 
100   bool store_table(dd::Table *install_table, int ndb_table_id);
101 
102  public:
103   Ndb_dd_client(class THD *thd);
104 
105   ~Ndb_dd_client();
106 
107   /**
108     @brief Acquire IX MDL on the schema
109 
110     @param schema_name Schema name
111 
112     @return true if the MDL was acquired successfully, false if not
113   */
114   bool mdl_lock_schema(const char *schema_name);
115   bool mdl_lock_schema_exclusive(const char *schema_name,
116                                  bool custom_lock_wait = false,
117                                  ulong lock_wait_timeout = 0);
118   bool mdl_lock_table(const char *schema_name, const char *table_name);
119   bool mdl_locks_acquire_exclusive(const char *schema_name,
120                                    const char *table_name,
121                                    bool custom_lock_wait = false,
122                                    ulong lock_wait_timeout = 0);
123   bool mdl_lock_logfile_group(const char *logfile_group_name,
124                               bool intention_exclusive);
125   bool mdl_lock_logfile_group_exclusive(const char *logfile_group_name,
126                                         bool custom_lock_wait = false,
127                                         ulong lock_wait_timeout = 0);
128   bool mdl_lock_tablespace(const char *tablespace_name,
129                            bool intention_exclusive);
130   bool mdl_lock_tablespace_exclusive(const char *tablespace_name,
131                                      bool custom_lock_wait = false,
132                                      ulong lock_wait_timeout = 0);
133   void mdl_locks_release();
134 
135   // Transaction handling functions
136   void commit();
137   void rollback();
138 
139   /*
140     @brief Turn off automatic rollback which otherwise occurs automatically
141            when Ndb_dd_client instance goes out of scope and no commit has
142            been called
143            This is useful when running as part of a higher level DDL command
144            which manages the transaction
145   */
disable_auto_rollback()146   void disable_auto_rollback() { m_auto_rollback = false; }
147 
148   bool get_engine(const char *schema_name, const char *table_name,
149                   dd::String_type *engine);
150 
151   bool rename_table(const char *old_schema_name, const char *old_table_name,
152                     const char *new_schema_name, const char *new_table_name,
153                     int new_table_id, int new_table_version,
154                     Ndb_referenced_tables_invalidator *invalidator = nullptr);
155   bool remove_table(const char *schema_name, const char *table_name,
156                     Ndb_referenced_tables_invalidator *invalidator = nullptr);
157   bool deserialize_table(const dd::sdi_t &sdi, dd::Table *table_def);
158   bool install_table(const char *schema_name, const char *table_name,
159                      const dd::sdi_t &sdi, int ndb_table_id,
160                      int ndb_table_version, size_t ndb_num_partitions,
161                      const std::string &tablespace_name, bool force_overwrite,
162                      Ndb_referenced_tables_invalidator *invalidator = nullptr);
163   bool migrate_table(const char *schema_name, const char *table_name,
164                      const unsigned char *frm_data, unsigned int unpacked_len,
165                      bool force_overwrite);
166   bool get_table(const char *schema_name, const char *table_name,
167                  const dd::Table **table_def);
168   bool table_exists(const char *schema_name, const char *table_name,
169                     bool &exists);
170   bool set_tablespace_id_in_table(const char *schema_name,
171                                   const char *table_name,
172                                   dd::Object_id tablespace_id);
173   bool set_object_id_and_version_in_table(const char *schema_name,
174                                           const char *table_name, int object_id,
175                                           int object_version);
176   bool store_table(dd::Table *install_table) const;
177 
178   bool fetch_all_schemas(std::map<std::string, const dd::Schema *> &);
179   bool fetch_schema_names(std::vector<std::string> *);
180   bool get_ndb_table_names_in_schema(const char *schema_name,
181                                      std::unordered_set<std::string> *names);
182   bool get_table_names_in_schema(const char *schema_name,
183                                  std::unordered_set<std::string> *ndb_tables,
184                                  std::unordered_set<std::string> *local_tables);
185   bool have_local_tables_in_schema(const char *schema_name,
186                                    bool *found_local_tables);
187   bool is_local_table(const char *schema_name, const char *table_name,
188                       bool &local_table);
189   bool get_schema(const char *schema_name, const dd::Schema **schema_def) const;
190   bool schema_exists(const char *schema_name, bool *schema_exists);
191   bool update_schema_version(const char *schema_name, unsigned int counter,
192                              unsigned int node_id);
193 
194   /*
195      @brief Lookup tablespace id from tablespace name
196 
197      @tablespace_name Name of tablespace
198      @tablespace_id Id of the tablespace
199 
200      @return true if tablespace found
201   */
202   bool lookup_tablespace_id(const char *tablespace_name,
203                             dd::Object_id *tablespace_id);
204   bool get_tablespace(const char *tablespace_name,
205                       const dd::Tablespace **tablespace_def);
206   bool tablespace_exists(const char *tablespace_name, bool &exists);
207   bool fetch_ndb_tablespace_names(std::unordered_set<std::string> &names);
208   bool install_tablespace(const char *tablespace_name,
209                           const std::vector<std::string> &data_file_names,
210                           int tablespace_id, int tablespace_version,
211                           bool force_overwrite);
212   bool drop_tablespace(const char *tablespace_name,
213                        bool fail_if_not_exists = true);
214   bool get_logfile_group(const char *logfile_group_name,
215                          const dd::Tablespace **logfile_group_def);
216   bool logfile_group_exists(const char *logfile_group_name, bool &exists);
217   bool fetch_ndb_logfile_group_names(std::unordered_set<std::string> &names);
218   bool install_logfile_group(const char *logfile_group_name,
219                              const std::vector<std::string> &undo_file_names,
220                              int logfile_group_id, int logfile_group_version,
221                              bool force_overwrite);
222   bool install_undo_file(const char *logfile_group_name,
223                          const char *undo_file_name);
224   bool drop_logfile_group(const char *logfile_group_name,
225                           bool fail_if_not_exists = true);
226   bool get_schema_uuid(dd::String_type *value) const;
227   bool update_schema_uuid(const char *value) const;
228 };
229 
230 #endif
231