~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/transaction_services.h

  • Committer: Brian Aker
  • Date: 2009-01-18 01:49:40 UTC
  • Revision ID: brian@gir-3.local-20090118014940-co9651fk7hla6gqg
Removed unused session param from list_open_tables()

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
5
 
 *  Copyright (c) 2010 Jay Pipes <jaypipes@gmail.com>
6
 
 *
7
 
 *  This program is free software; you can redistribute it and/or modify
8
 
 *  it under the terms of the GNU General Public License as published by
9
 
 *  the Free Software Foundation; version 2 of the License.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
/**
22
 
 * @file Transaction processing code
23
 
 */
24
 
 
25
 
#ifndef DRIZZLED_TRANSACTION_SERVICES_H
26
 
#define DRIZZLED_TRANSACTION_SERVICES_H
27
 
 
28
 
#include "drizzled/atomics.h"
29
 
#include "drizzled/message/transaction.pb.h"
30
 
 
31
 
namespace drizzled
32
 
{
33
 
 
34
 
/* some forward declarations needed */
35
 
namespace plugin
36
 
{
37
 
  class MonitoredInTransaction;
38
 
  class XaResourceManager;
39
 
  class XaStorageEngine;
40
 
  class TransactionalStorageEngine;
41
 
}
42
 
 
43
 
class Session;
44
 
class NamedSavepoint;
45
 
class Field;
46
 
 
47
 
/**
48
 
 * This is a class which manages the XA transaction processing
49
 
 * in the server
50
 
 */
51
 
class TransactionServices
52
 
{
53
 
public:
54
 
  static const size_t DEFAULT_RECORD_SIZE= 100;
55
 
  
56
 
  TransactionServices();
57
 
 
58
 
  /**
59
 
   * Singleton method
60
 
   * Returns the singleton instance of TransactionServices
61
 
   */
62
 
  static inline TransactionServices &singleton()
63
 
  {
64
 
    static TransactionServices transaction_services;
65
 
    return transaction_services;
66
 
  }
67
 
 
68
 
  /**
69
 
   * Returns true if the transaction manager should construct
70
 
   * Transaction and Statement messages, false otherwise.
71
 
   */
72
 
  bool shouldConstructMessages();
73
 
  /**
74
 
   * Method which returns the active Transaction message
75
 
   * for the supplied Session.  If one is not found, a new Transaction
76
 
   * message is allocated, initialized, and returned. It is possible that
77
 
   * we may want to NOT increment the transaction id for a new Transaction
78
 
   * object (e.g., splitting up Transactions into smaller chunks). The
79
 
   * should_inc_trx_id flag controls if we do this.
80
 
   *
81
 
   * @param in_session The session processing the transaction
82
 
   * @param should_inc_trx_id If true, increments the transaction id for a new trx
83
 
   */
84
 
  message::Transaction *getActiveTransactionMessage(Session *in_session,
85
 
                                                    bool should_inc_trx_id= true);
86
 
  /** 
87
 
   * Method which attaches a transaction context
88
 
   * the supplied transaction based on the supplied Session's
89
 
   * transaction information.  This method also ensure the
90
 
   * transaction message is attached properly to the Session object
91
 
   *
92
 
   * @param in_transaction The transaction message to initialize
93
 
   * @param in_session The Session processing this transaction
94
 
   * @param should_inc_trx_id If true, increments the transaction id for a new trx
95
 
   */
96
 
  void initTransactionMessage(message::Transaction &in_transaction,
97
 
                              Session *in_session,
98
 
                              bool should_inc_trx_id);
99
 
  /** 
100
 
   * Helper method which finalizes data members for the 
101
 
   * supplied transaction's context.
102
 
   *
103
 
   * @param in_transaction The transaction message to finalize 
104
 
   * @param in_session The Session processing this transaction
105
 
   */
106
 
  void finalizeTransactionMessage(message::Transaction &in_transaction, Session *in_session);
107
 
  /**
108
 
   * Helper method which deletes transaction memory and
109
 
   * unsets Session's transaction and statement messages.
110
 
   */
111
 
  void cleanupTransactionMessage(message::Transaction *in_transaction,
112
 
                                 Session *in_session);
113
 
 
114
 
  /**
115
 
   * Helper method which initializes a Statement message
116
 
   *
117
 
   * @param statement The statement to initialize
118
 
   * @param in_type The type of the statement
119
 
   * @param in_session The session processing this statement
120
 
   */
121
 
  void initStatementMessage(message::Statement &statement,
122
 
                            message::Statement::Type in_type,
123
 
                            Session *in_session);
124
 
  /**
125
 
   * Finalizes a Statement message and sets the Session's statement
126
 
   * message to NULL.
127
 
   *
128
 
   * @param statement The statement to initialize
129
 
   * @param in_session The session processing this statement
130
 
   */
131
 
  void finalizeStatementMessage(message::Statement &statement,
132
 
                                Session *in_session);
133
 
  /** Helper method which returns an initialized Statement message for methods
134
 
   * doing insertion of data.
135
 
   *
136
 
   * @param[in] in_session Pointer to the Session doing the processing
137
 
   * @param[in] in_table Pointer to the Table object being inserted into
138
 
   * @param[out] next_segment_id The next Statement segment id to be used
139
 
   */
140
 
  message::Statement &getInsertStatement(Session *in_session,
141
 
                                         Table *in_table,
142
 
                                         uint32_t *next_segment_id);
143
 
 
144
 
  /**
145
 
   * Helper method which initializes the header message for
146
 
   * insert operations.
147
 
   *
148
 
   * @param[in,out] statement Statement message container to modify
149
 
   * @param[in] in_session Pointer to the Session doing the processing
150
 
   * @param[in] in_table Pointer to the Table being inserted into
151
 
   */
152
 
  void setInsertHeader(message::Statement &statement,
153
 
                       Session *in_session,
154
 
                       Table *in_table);
155
 
  /**
156
 
   * Helper method which returns an initialized Statement
157
 
   * message for methods doing updates of data.
158
 
   *
159
 
   * @param[in] in_session Pointer to the Session doing the processing
160
 
   * @param[in] in_table Pointer to the Table object being updated
161
 
   * @param[in] old_record Pointer to the old data in the record
162
 
   * @param[in] new_record Pointer to the new data in the record
163
 
   * @param[out] next_segment_id The next Statement segment id to be used
164
 
   */
165
 
  message::Statement &getUpdateStatement(Session *in_session,
166
 
                                         Table *in_table,
167
 
                                         const unsigned char *old_record, 
168
 
                                         const unsigned char *new_record,
169
 
                                         uint32_t *next_segment_id);
170
 
  /**
171
 
   * Helper method which initializes the header message for
172
 
   * update operations.
173
 
   *
174
 
   * @param[in,out] statement Statement message container to modify
175
 
   * @param[in] in_session Pointer to the Session doing the processing
176
 
   * @param[in] in_table Pointer to the Table being updated
177
 
   * @param[in] old_record Pointer to the old data in the record
178
 
   * @param[in] new_record Pointer to the new data in the record
179
 
   */
180
 
  void setUpdateHeader(message::Statement &statement,
181
 
                       Session *in_session,
182
 
                       Table *in_table,
183
 
                       const unsigned char *old_record, 
184
 
                       const unsigned char *new_record);
185
 
  /**
186
 
   * Helper method which returns an initialized Statement
187
 
   * message for methods doing deletion of data.
188
 
   *
189
 
   * @param[in] in_session Pointer to the Session doing the processing
190
 
   * @param[in] in_table Pointer to the Table object being deleted from
191
 
   * @param[out] next_segment_id The next Statement segment id to be used
192
 
   */
193
 
  message::Statement &getDeleteStatement(Session *in_session,
194
 
                                         Table *in_table,
195
 
                                         uint32_t *next_segment_id);
196
 
 
197
 
  /**
198
 
   * Helper method which initializes the header message for
199
 
   * insert operations.
200
 
   *
201
 
   * @param[in,out] statement Statement message container to modify
202
 
   * @param[in] in_session Pointer to the Session doing the processing
203
 
   * @param[in] in_table Pointer to the Table being deleted from
204
 
   */
205
 
  void setDeleteHeader(message::Statement &statement,
206
 
                       Session *in_session,
207
 
                       Table *in_table);
208
 
  /** 
209
 
   * Commits a normal transaction (see above) and pushes the transaction
210
 
   * message out to the replicators.
211
 
   *
212
 
   * @param in_session Pointer to the Session committing the transaction
213
 
   */
214
 
  int commitTransactionMessage(Session *in_session);
215
 
  /** 
216
 
   * Marks the current active transaction message as being rolled back and
217
 
   * pushes the transaction message out to replicators.
218
 
   *
219
 
   * @param in_session Pointer to the Session committing the transaction
220
 
   */
221
 
  void rollbackTransactionMessage(Session *in_session);
222
 
  /**
223
 
   * Rolls back the current statement, deleting the last Statement out of
224
 
   * the current Transaction message.
225
 
   *
226
 
   * @note This depends on having clear statement boundaries (i.e., one
227
 
   * Statement message per actual SQL statement.
228
 
   */
229
 
  void rollbackStatementMessage(Session *in_session);
230
 
  /**
231
 
   * Creates a new InsertRecord GPB message and pushes it to
232
 
   * replicators.
233
 
   *
234
 
   * @param in_session Pointer to the Session which has inserted a record
235
 
   * @param in_table Pointer to the Table containing insert information
236
 
   *
237
 
   * Grr, returning "true" here on error because of the cursor
238
 
   * reversed bool return crap...fix that.
239
 
   */
240
 
  bool insertRecord(Session *in_session, Table *in_table);
241
 
  /**
242
 
   * Creates a new UpdateRecord GPB message and pushes it to
243
 
   * replicators.
244
 
   *
245
 
   * @param in_session Pointer to the Session which has updated a record
246
 
   * @param in_table Pointer to the Table containing update information
247
 
   * @param old_record Pointer to the raw bytes representing the old record/row
248
 
   * @param new_record Pointer to the raw bytes representing the new record/row 
249
 
   */
250
 
  void updateRecord(Session *in_session, 
251
 
                    Table *in_table, 
252
 
                    const unsigned char *old_record, 
253
 
                    const unsigned char *new_record);
254
 
  /**
255
 
   * Creates a new DeleteRecord GPB message and pushes it to
256
 
   * replicators.
257
 
   *
258
 
   * @param in_session Pointer to the Session which has deleted a record
259
 
   * @param in_table Pointer to the Table containing delete information
260
 
   * @param use_update_record If true, uses the values from the update row instead
261
 
   */
262
 
  void deleteRecord(Session *in_session, Table *in_table, bool use_update_record= false);
263
 
 
264
 
  /**
265
 
   * Used to undo effects of a failed statement.
266
 
   *
267
 
   * An SQL statement, like an UPDATE, that affects multiple rows could
268
 
   * potentially fail mid-way through processing the rows. In such a case,
269
 
   * the successfully modified rows that preceeded the failing row would
270
 
   * have been added to the Statement message. This method is used for
271
 
   * rolling back that change.
272
 
   *
273
 
   * @note
274
 
   * This particular failure is seen on column constraint violations
275
 
   * during a multi-row UPDATE and a multi-row INSERT..SELECT.
276
 
   *
277
 
   * @param in_session Pointer to the Session containing the Statement
278
 
   * @param count The number of records to remove from Statement.
279
 
   *
280
 
   * @retval true Successfully removed 'count' records
281
 
   * @retval false Failure
282
 
   */
283
 
  bool removeStatementRecords(Session *in_session, uint32_t count);
284
 
 
285
 
  /**
286
 
   * Creates a CreateSchema Statement GPB message and adds it
287
 
   * to the Session's active Transaction GPB message for pushing
288
 
   * out to the replicator streams.
289
 
   *
290
 
   * @param[in] in_session Pointer to the Session which issued the statement
291
 
   * @param[in] schema message::Schema message describing new schema
292
 
   */
293
 
  void createSchema(Session *in_session, const message::Schema &schema);
294
 
  /**
295
 
   * Creates a DropSchema Statement GPB message and adds it
296
 
   * to the Session's active Transaction GPB message for pushing
297
 
   * out to the replicator streams.
298
 
   *
299
 
   * @param[in] in_session Pointer to the Session which issued the statement
300
 
   * @param[in] schema_name message::Schema message describing new schema
301
 
   */
302
 
  void dropSchema(Session *in_session, const std::string &schema_name);
303
 
  /**
304
 
   * Creates a CreateTable Statement GPB message and adds it
305
 
   * to the Session's active Transaction GPB message for pushing
306
 
   * out to the replicator streams.
307
 
   *
308
 
   * @param[in] in_session Pointer to the Session which issued the statement
309
 
   * @param[in] table message::Table message describing new schema
310
 
   */
311
 
  void createTable(Session *in_session, const message::Table &table);
312
 
  /**
313
 
   * Creates a DropTable Statement GPB message and adds it
314
 
   * to the Session's active Transaction GPB message for pushing
315
 
   * out to the replicator streams.
316
 
   *
317
 
   * @param[in] in_session Pointer to the Session which issued the statement
318
 
   * @param[in] schema_name The schema of the table being dropped
319
 
   * @param[in] table_name The table name of the table being dropped
320
 
   * @param[in] if_exists Did the user specify an IF EXISTS clause?
321
 
   */
322
 
  void dropTable(Session *in_session,
323
 
                     const std::string &schema_name,
324
 
                     const std::string &table_name,
325
 
                     bool if_exists);
326
 
  /**
327
 
   * Creates a TruncateTable Statement GPB message and adds it
328
 
   * to the Session's active Transaction GPB message for pushing
329
 
   * out to the replicator streams.
330
 
   *
331
 
   * @param[in] in_session Pointer to the Session which issued the statement
332
 
   * @param[in] in_table The Table being truncated
333
 
   */
334
 
  void truncateTable(Session *in_session, Table *in_table);
335
 
  /**
336
 
   * Creates a new RawSql GPB message and pushes it to 
337
 
   * replicators.
338
 
   *
339
 
   * @TODO With a real data dictionary, this really shouldn't
340
 
   * be needed.  CREATE TABLE would map to insertRecord call
341
 
   * on the I_S, etc.  Not sure what to do with administrative
342
 
   * commands like CHECK TABLE, though..
343
 
   *
344
 
   * @param in_session Pointer to the Session which issued the statement
345
 
   * @param query Query string
346
 
   */
347
 
  void rawStatement(Session *in_session, const std::string &query);
348
 
  /* transactions: interface to plugin::StorageEngine functions */
349
 
  int commitPhaseOne(Session *session, bool all);
350
 
  int rollbackTransaction(Session *session, bool all);
351
 
 
352
 
  /* transactions: these functions never call plugin::StorageEngine functions directly */
353
 
  int commitTransaction(Session *session, bool all);
354
 
  int autocommitOrRollback(Session *session, int error);
355
 
 
356
 
  /* savepoints */
357
 
  int rollbackToSavepoint(Session *session, NamedSavepoint &sv);
358
 
  int setSavepoint(Session *session, NamedSavepoint &sv);
359
 
  int releaseSavepoint(Session *session, NamedSavepoint &sv);
360
 
 
361
 
  /**
362
 
   * Marks a storage engine as participating in a statement
363
 
   * transaction.
364
 
   *
365
 
   * @note
366
 
   * 
367
 
   * This method is idempotent
368
 
   *
369
 
   * @todo
370
 
   *
371
 
   * This method should not be called more than once per resource
372
 
   * per statement, and therefore should not need to be idempotent.
373
 
   * Put in assert()s to test this.
374
 
   *
375
 
   * @param[in] session Session pointer
376
 
   * @param[in] monitored Descriptor for the resource which will be participating
377
 
   * @param[in] engine Pointer to the TransactionalStorageEngine resource
378
 
   */
379
 
  void registerResourceForStatement(Session *session,
380
 
                                    plugin::MonitoredInTransaction *monitored,
381
 
                                    plugin::TransactionalStorageEngine *engine);
382
 
 
383
 
  /**
384
 
   * Marks an XA storage engine as participating in a statement
385
 
   * transaction.
386
 
   *
387
 
   * @note
388
 
   * 
389
 
   * This method is idempotent
390
 
   *
391
 
   * @todo
392
 
   *
393
 
   * This method should not be called more than once per resource
394
 
   * per statement, and therefore should not need to be idempotent.
395
 
   * Put in assert()s to test this.
396
 
   *
397
 
   * @param[in] session Session pointer
398
 
   * @param[in] monitored Descriptor for the resource which will be participating
399
 
   * @param[in] engine Pointer to the TransactionalStorageEngine resource
400
 
   * @param[in] resource_manager Pointer to the XaResourceManager resource manager
401
 
   */
402
 
  void registerResourceForStatement(Session *session,
403
 
                                    plugin::MonitoredInTransaction *monitored,
404
 
                                    plugin::TransactionalStorageEngine *engine,
405
 
                                    plugin::XaResourceManager *resource_manager);
406
 
 
407
 
  /**
408
 
   * Registers a resource manager in the "normal" transaction.
409
 
   *
410
 
   * @note
411
 
   *
412
 
   * This method is idempotent and must be idempotent
413
 
   * because it can be called both by the above 
414
 
   * TransactionServices::registerResourceForStatement(),
415
 
   * which occurs at the beginning of each SQL statement,
416
 
   * and also manually when a BEGIN WORK/START TRANSACTION
417
 
   * statement is executed. If the latter case (BEGIN WORK)
418
 
   * is called, then subsequent contained statement transactions
419
 
   * will call this method as well.
420
 
   *
421
 
   * @note
422
 
   *
423
 
   * This method checks to see if the supplied resource
424
 
   * is also registered in the statement transaction, and
425
 
   * if not, registers the resource in the statement
426
 
   * transaction.  This happens ONLY when the user has
427
 
   * called BEGIN WORK/START TRANSACTION, which is the only
428
 
   * time when this method is called except from the
429
 
   * TransactionServices::registerResourceForStatement method.
430
 
   */
431
 
  void registerResourceForTransaction(Session *session,
432
 
                                      plugin::MonitoredInTransaction *monitored,
433
 
                                      plugin::TransactionalStorageEngine *engine);
434
 
  void registerResourceForTransaction(Session *session,
435
 
                                      plugin::MonitoredInTransaction *monitored,
436
 
                                      plugin::TransactionalStorageEngine *engine,
437
 
                                      plugin::XaResourceManager *resource_manager);
438
 
 
439
 
  uint64_t getCurrentTransactionId(Session *session);
440
 
 
441
 
  void allocateNewTransactionId();
442
 
 
443
 
  /**************
444
 
   * Events API
445
 
   **************/
446
 
 
447
 
  /**
448
 
   * Send server startup event.
449
 
   *
450
 
   * @param session Session pointer
451
 
   *
452
 
   * @retval true Success
453
 
   * @retval false Failure
454
 
   */
455
 
  bool sendStartupEvent(Session *session);
456
 
 
457
 
  /**
458
 
   * Send server shutdown event.
459
 
   *
460
 
   * @param session Session pointer
461
 
   *
462
 
   * @retval true Success
463
 
   * @retval false Failure
464
 
   */
465
 
  bool sendShutdownEvent(Session *session);
466
 
 
467
 
private:
468
 
 
469
 
  /**
470
 
   * Checks if a field has been updated 
471
 
   *
472
 
   * @param current_field Pointer to the field to check if it is updated 
473
 
   * @in_table Pointer to the Table containing update information
474
 
   * @param old_record Pointer to the raw bytes representing the old record/row
475
 
   * @param new_record Pointer to the raw bytes representing the new record/row
476
 
   */
477
 
  bool isFieldUpdated(Field *current_field,
478
 
                      Table *in_table,
479
 
                      const unsigned char *old_record,
480
 
                      const unsigned char *new_record);
481
 
 
482
 
  /**
483
 
   * Create a Transaction that contains event information and send it off.
484
 
   *
485
 
   * This differs from other uses of Transaction in that we don't use the
486
 
   * message associated with Session. We create a totally new message and
487
 
   * use it.
488
 
   *
489
 
   * @param session Session pointer
490
 
   * @param event Event message to send
491
 
   *
492
 
   * @note Used by the public Events API.
493
 
   *
494
 
   * @returns Non-zero on error
495
 
   */
496
 
  int sendEvent(Session *session, const message::Event &event);
497
 
 
498
 
  /**
499
 
   * Helper method which checks the UpdateHeader to determine 
500
 
   * if it needs to be finalized.  
501
 
   *
502
 
   * @param[in] statement Statement message container to check 
503
 
   * @param[in] in_table Pointer to the Table being updated
504
 
   * @param[in] old_record Pointer to the old data in the record
505
 
   * @param[in] new_record Pointer to the new data in the record
506
 
   */
507
 
  bool useExistingUpdateHeader(message::Statement &statement,
508
 
                               Table *in_table,
509
 
                               const unsigned char *old_record,
510
 
                               const unsigned char *new_record);
511
 
 
512
 
  plugin::XaStorageEngine *xa_storage_engine;
513
 
};
514
 
 
515
 
} /* namespace drizzled */
516
 
 
517
 
#endif /* DRIZZLED_TRANSACTION_SERVICES_H */