~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/rpl_injector.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
15
 
 
16
#ifndef INJECTOR_H
 
17
#define INJECTOR_H
 
18
 
 
19
/* Pull in 'byte', 'my_off_t', and 'uint32' */
 
20
#include <my_global.h>
 
21
#include <my_bitmap.h>
 
22
 
 
23
#include "rpl_constants.h"
 
24
 
 
25
/* Forward declarations */
 
26
class handler;
 
27
class MYSQL_BIN_LOG;
 
28
struct st_table;
 
29
 
 
30
typedef st_table TABLE;
 
31
 
 
32
/*
 
33
  Injector to inject rows into the MySQL server.
 
34
  
 
35
  The injector class is used to notify the MySQL server of new rows that have
 
36
  appeared outside of MySQL control.
 
37
 
 
38
  The original purpose of this is to allow clusters---which handle replication
 
39
  inside the cluster through other means---to insert new rows into binary log.
 
40
  Note, however, that the injector should be used whenever rows are altered in
 
41
  any manner that is outside of MySQL server visibility and which therefore
 
42
  are not seen by the MySQL server.
 
43
 */
 
44
class injector 
 
45
{
 
46
public:
 
47
 
 
48
  /*
 
49
    Get an instance of the injector.
 
50
 
 
51
    DESCRIPTION
 
52
      The injector is a Singleton, so this static function return the
 
53
      available instance of the injector.
 
54
 
 
55
    RETURN VALUE
 
56
      A pointer to the available injector object.
 
57
  */
 
58
  static injector *instance();
 
59
 
 
60
  /*
 
61
    Delete the singleton instance (if allocated). Used during server shutdown.
 
62
  */
 
63
  static void free_instance();
 
64
 
 
65
    /*
 
66
      A transaction where rows can be added.
 
67
 
 
68
      DESCRIPTION
 
69
        The transaction class satisfy the **CopyConstructible** and
 
70
        **Assignable** requirements.  Note that the transaction is *not*
 
71
        default constructible.
 
72
     */
 
73
    class transaction {
 
74
      friend class injector;
 
75
    public:
 
76
      /* Convenience definitions */
 
77
      typedef uchar* record_type;
 
78
      typedef uint32 server_id_type;
 
79
 
 
80
      /*
 
81
        Table reference.
 
82
 
 
83
        RESPONSIBILITY
 
84
 
 
85
          The class contains constructors to handle several forms of
 
86
          references to tables.  The constructors can implicitly be used to
 
87
          construct references from, e.g., strings containing table names.
 
88
 
 
89
        EXAMPLE
 
90
 
 
91
          The class is intended to be used *by value*.  Please, do not try to
 
92
          construct objects of this type using 'new'; instead construct an
 
93
          object, possibly a temporary object.  For example:
 
94
 
 
95
            injector::transaction::table tbl(share->table, true);
 
96
            MY_BITMAP cols;
 
97
            bitmap_init(&cols, NULL, (i + 7) / 8, false);
 
98
            inj->write_row(::server_id, tbl, &cols, row_data);
 
99
 
 
100
          or
 
101
 
 
102
            MY_BITMAP cols;
 
103
            bitmap_init(&cols, NULL, (i + 7) / 8, false);
 
104
            inj->write_row(::server_id, 
 
105
                           injector::transaction::table(share->table, true), 
 
106
                           &cols, row_data);
 
107
 
 
108
          This will work, be more efficient, and have greater chance of
 
109
          inlining, not run the risk of losing pointers.
 
110
 
 
111
        COLLABORATION
 
112
 
 
113
          injector::transaction
 
114
            Provide a flexible interface to the representation of tables.
 
115
 
 
116
      */
 
117
      class table 
 
118
      {
 
119
      public:
 
120
        table(TABLE *table, bool is_transactional) 
 
121
            : m_table(table), m_is_transactional(is_transactional)
 
122
        { 
 
123
        }
 
124
 
 
125
        char const *db_name() const { return m_table->s->db.str; }
 
126
        char const *table_name() const { return m_table->s->table_name.str; }
 
127
        TABLE *get_table() const { return m_table; }
 
128
        bool is_transactional() const { return m_is_transactional; }
 
129
 
 
130
      private:
 
131
        TABLE *m_table;
 
132
        bool m_is_transactional;
 
133
      };
 
134
 
 
135
      /*
 
136
        Binlog position as a structure.
 
137
      */
 
138
      class binlog_pos {
 
139
        friend class transaction;
 
140
      public:
 
141
        char const *file_name() const { return m_file_name; }
 
142
        my_off_t file_pos() const { return m_file_pos; }
 
143
 
 
144
      private:
 
145
        char const *m_file_name;
 
146
        my_off_t m_file_pos;
 
147
      };
 
148
 
 
149
      transaction() : m_thd(NULL) { }
 
150
      transaction(transaction const&);
 
151
      ~transaction();
 
152
 
 
153
      /* Clear transaction, i.e., make calls to 'good()' return false. */
 
154
      void clear() { m_thd= NULL; }
 
155
 
 
156
      /* Is the transaction in a good state? */
 
157
      bool good() const { return m_thd != NULL; }
 
158
 
 
159
      /* Default assignment operator: standard implementation */
 
160
      transaction& operator=(transaction t) {
 
161
        swap(t);
 
162
        return *this;
 
163
      }
 
164
      
 
165
      /*
 
166
 
 
167
        DESCRIPTION
 
168
 
 
169
          Register table for use within the transaction.  All tables
 
170
          that are going to be used need to be registered before being
 
171
          used below.  The member function will fail with an error if
 
172
          use_table() is called after any *_row() function has been
 
173
          called for the transaction.
 
174
 
 
175
        RETURN VALUE
 
176
 
 
177
          0         All OK
 
178
          >0        Failure
 
179
 
 
180
       */
 
181
      int use_table(server_id_type sid, table tbl);
 
182
 
 
183
      /*
 
184
        Add a 'write row' entry to the transaction.
 
185
      */
 
186
      int write_row (server_id_type sid, table tbl, 
 
187
                     MY_BITMAP const *cols, size_t colcnt,
 
188
                     record_type record);
 
189
 
 
190
      /*
 
191
        Add a 'delete row' entry to the transaction.
 
192
      */
 
193
      int delete_row(server_id_type sid, table tbl, 
 
194
                     MY_BITMAP const *cols, size_t colcnt,
 
195
                     record_type record);
 
196
 
 
197
      /*
 
198
        Add an 'update row' entry to the transaction.
 
199
      */
 
200
      int update_row(server_id_type sid, table tbl, 
 
201
                     MY_BITMAP const *cols, size_t colcnt,
 
202
                     record_type before, record_type after);
 
203
 
 
204
      /*
 
205
        Commit a transaction.
 
206
 
 
207
        This member function will clean up after a sequence of *_row calls by,
 
208
        for example, releasing resource and unlocking files.
 
209
      */
 
210
      int commit();
 
211
 
 
212
      /*
 
213
        Get the position for the start of the transaction.
 
214
 
 
215
        Returns the position in the binary log of the first event in this
 
216
        transaction. If no event is yet written, the position where the event
 
217
        *will* be written is returned. This position is known, since a
 
218
        new_transaction() will lock the binary log and prevent any other
 
219
        writes to the binary log.
 
220
      */
 
221
      binlog_pos start_pos() const;
 
222
 
 
223
    private:
 
224
      /* Only the injector may construct these object */
 
225
      transaction(MYSQL_BIN_LOG *, THD *);
 
226
 
 
227
      void swap(transaction& o) {
 
228
        /* std::swap(m_start_pos, o.m_start_pos); */
 
229
        {
 
230
          binlog_pos const tmp= m_start_pos;
 
231
          m_start_pos= o.m_start_pos;
 
232
          o.m_start_pos= tmp;
 
233
        }
 
234
 
 
235
        /* std::swap(m_thd, o.m_thd); */
 
236
        {
 
237
          THD* const tmp= m_thd;
 
238
          m_thd= o.m_thd;
 
239
          o.m_thd= tmp;
 
240
        }
 
241
        {
 
242
          enum_state const tmp= m_state;
 
243
          m_state= o.m_state;
 
244
          o.m_state= tmp;
 
245
        }
 
246
      }
 
247
 
 
248
      enum enum_state
 
249
      {
 
250
        START_STATE,                            /* Start state */
 
251
        TABLE_STATE,      /* At least one table has been registered */
 
252
        ROW_STATE,          /* At least one row has been registered */
 
253
        STATE_COUNT               /* State count and sink state */
 
254
      } m_state;
 
255
 
 
256
      /*
 
257
        Check and update the state.
 
258
 
 
259
        PARAMETER(S)
 
260
 
 
261
          target_state
 
262
              The state we are moving to: TABLE_STATE if we are
 
263
              writing a table and ROW_STATE if we are writing a row.
 
264
 
 
265
        DESCRIPTION
 
266
 
 
267
          The internal state will be updated to the target state if
 
268
          and only if it is a legal move.  The only legal moves are:
 
269
 
 
270
              START_STATE -> START_STATE
 
271
              START_STATE -> TABLE_STATE
 
272
              TABLE_STATE -> TABLE_STATE
 
273
              TABLE_STATE -> ROW_STATE
 
274
 
 
275
          That is:
 
276
          - It is not possible to write any row before having written at
 
277
            least one table
 
278
          - It is not possible to write a table after at least one row
 
279
            has been written
 
280
 
 
281
        RETURN VALUE
 
282
 
 
283
           0    All OK
 
284
          -1    Incorrect call sequence
 
285
       */
 
286
      int check_state(enum_state const target_state)
 
287
      {
 
288
#ifndef DBUG_OFF
 
289
        static char const *state_name[] = {
 
290
          "START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT"
 
291
        };
 
292
 
 
293
        DBUG_ASSERT(0 <= target_state && target_state <= STATE_COUNT);
 
294
        DBUG_PRINT("info", ("In state %s", state_name[m_state]));
 
295
#endif
 
296
 
 
297
        if (m_state <= target_state && target_state <= m_state + 1 &&
 
298
            m_state < STATE_COUNT)
 
299
          m_state= target_state;
 
300
        else
 
301
          m_state= STATE_COUNT;
 
302
        return m_state == STATE_COUNT ? 1 : 0;
 
303
      }
 
304
 
 
305
 
 
306
      binlog_pos m_start_pos;
 
307
      THD *m_thd;
 
308
    };
 
309
 
 
310
    /* 
 
311
       Create a new transaction.  This member function will prepare for a
 
312
       sequence of *_row calls by, for example, reserving resources and
 
313
       locking files. There are two overloaded alternatives: one returning a
 
314
       transaction by value and one using placement semantics. The following
 
315
       two calls are equivalent, with the exception that the latter will
 
316
       overwrite the transaction.
 
317
 
 
318
         injector::transaction trans1= inj->new_trans(thd);
 
319
 
 
320
         injector::transaction trans2;
 
321
         inj->new_trans(thd, &trans);
 
322
     */
 
323
    transaction new_trans(THD *);
 
324
    void        new_trans(THD *, transaction *);
 
325
 
 
326
    int record_incident(THD*, Incident incident);
 
327
    int record_incident(THD*, Incident incident, LEX_STRING const message);
 
328
 
 
329
private:
 
330
    explicit injector();
 
331
    ~injector() { }             /* Nothing needs to be done */
 
332
    injector(injector const&);  /* You're not allowed to copy injector
 
333
                                   instances.
 
334
                                */ 
 
335
};
 
336
 
 
337
#endif /* INJECTOR_H */