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_BINLOG_CLIENT_H
26 #define NDB_BINLOG_CLIENT_H
27 
28 #include <string>
29 
30 #include "my_compiler.h"
31 #include "my_inttypes.h"
32 #include "storage/ndb/include/ndbapi/NdbDictionary.hpp"
33 
34 struct NDB_SHARE;
35 struct st_conflict_fn_def;
36 struct st_conflict_fn_arg;
37 
38 namespace dd {
39 class Table;
40 }
41 
42 class Ndb_binlog_client {
43   class THD *m_thd;
44   const char *m_dbname;
45   const char *m_tabname;
46 
47   /**
48    * @brief log_warning, push the message as warning for user threads and
49    *                     write the message to log file for other threads
50    */
51   void log_warning(uint code, const char *fmt, ...) const
52       MY_ATTRIBUTE((format(printf, 3, 4)));
53 
54   /**
55    * @brief event_name_for_table, generate name for the event for this table
56    *
57    * @param db             database of table
58    * @param table_name     name of table
59    * @param full           create name for event with all columns
60    * @return the returned event name
61    */
62   static std::string event_name_for_table(const char *db,
63                                           const char *table_name, bool full);
64 
65  public:
66   Ndb_binlog_client(class THD *, const char *dbname, const char *tabname);
67   ~Ndb_binlog_client();
68 
69   int read_and_apply_replication_info(Ndb *ndb, NDB_SHARE *share,
70                                       const NdbDictionary::Table *ndbtab,
71                                       uint server_id);
72   int apply_replication_info(Ndb *ndb, NDB_SHARE *share,
73                              const NdbDictionary::Table *ndbtab,
74                              const st_conflict_fn_def *conflict_fn,
75                              const st_conflict_fn_arg *args, uint num_args,
76                              uint32 binlog_flags);
77   bool read_replication_info(Ndb *ndb, const char *db, const char *table_name,
78                              uint server_id, uint32 *binlog_flags,
79                              const st_conflict_fn_def **conflict_fn,
80                              struct st_conflict_fn_arg *args, uint *num_args);
81 
82   /**
83    * @brief table_should_have_event, decide if a NdbEvent should be created
84    * for the current table. Normally a NdbEvent is created for the table
85    * unless the table will never been binlogged(like the distributed
86    * privilege tables).
87    *
88    * NOTE! Even if the MySQL Server who creates the  event will not use
89    * it, there might be several other MySQL Server(s) who will need the
90    * event. Even if they could of course create the event while opening
91    * the table, that's an unnecessary chance for race conditions and overload
92    * to occur.
93    *
94    * @return true if table should have a NdbEvent
95    */
96   bool table_should_have_event(NDB_SHARE *share,
97                                const NdbDictionary::Table *ndbtab) const;
98 
99   /**
100    * @brief table_should_have_event_op, decide if a NdbEventOperation
101    * should be crated for the current table. Only table which need to
102    * be binlogged would create such a event operation. The exeception
103    * is the ndb_schema table who subscribes to events for schema distribution.
104    * @return  true if table should have a NdbEventOperation
105    */
106   bool table_should_have_event_op(const NDB_SHARE *share);
107 
108   /**
109    * @brief event_exists_for_table, check if event already exists for this
110    *        table
111    *
112    * @param ndb    Ndb pointer
113    * @param share  NDB_SHARE pointer
114    *
115    * @return true if event already exists
116    */
117   bool event_exists_for_table(Ndb *ndb, const NDB_SHARE *share) const;
118 
119   int create_event(Ndb *ndb, const NdbDictionary::Table *ndbtab,
120                    const NDB_SHARE *share);
121   bool create_event_data(NDB_SHARE *share, const dd::Table *table_def,
122                          class Ndb_event_data **event_data) const;
123   int create_event_op(NDB_SHARE *share, const NdbDictionary::Table *ndbtab,
124                       const Ndb_event_data *event_data);
125 
126   /**
127    * @brief drop_events_for_table, drop all binlog events for the table
128    *        from NDB
129    *
130    * NOTE! There might be 2 different events created for binlogging the table
131    * and it's not possible to know which ones have been create as that depends
132    * on the settings of the MySQL Server who need them. Drop all.
133    *
134    * @param thd            thread context
135    * @param ndb            Ndb pointer
136    * @param dbname         database of table
137    * @param tabname        name of table
138    */
139   static void drop_events_for_table(THD *thd, Ndb *ndb, const char *dbname,
140                                     const char *tabname);
141 };
142 
143 #endif
144