1/* Copyright (C) 2007-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
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 Street, Fifth Floor, Boston, MA 02111-1301 USA */
15
16#include "maria_def.h"
17#include "trnman.h"
18
19/**
20 writes a COMMIT record to log and commits transaction in memory
21
22 @param trn transaction
23
24 @return Operation status
25 @retval 0 ok
26 @retval 1 error (disk error or out of memory)
27*/
28
29int ma_commit(TRN *trn)
30{
31 int res;
32 LSN commit_lsn;
33 LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS];
34 DBUG_ENTER("ma_commit");
35
36 DBUG_ASSERT(trn->rec_lsn == LSN_IMPOSSIBLE);
37 if (trn->undo_lsn == 0) /* no work done, rollback (cheaper than commit) */
38 DBUG_RETURN(trnman_rollback_trn(trn));
39 /*
40 - if COMMIT record is written before trnman_commit_trn():
41 if Checkpoint comes in the middle it will see trn is not committed,
42 then if crash, Recovery might roll back trn (if MY_MIN(rec_lsn) is after
43 COMMIT record) and this is not an issue as
44 * transaction's updates were not made visible to other transactions
45 * "commit ok" was not sent to client
46 Alternatively, Recovery might commit trn (if MY_MIN(rec_lsn) is before COMMIT
47 record), which is ok too. All in all it means that "trn committed" is not
48 100% equal to "COMMIT record written".
49 - if COMMIT record is written after trnman_commit_trn():
50 if crash happens between the two, trn will be rolled back which is an
51 issue (transaction's updates were made visible to other transactions).
52 So we need to go the first way.
53
54 Note that we have to use | here to ensure that all calls are made.
55 */
56
57 /*
58 We do not store "thd->transaction.xid_state.xid" for now, it will be
59 needed only when we support XA.
60 */
61 res= (translog_write_record(&commit_lsn, LOGREC_COMMIT,
62 trn, NULL, 0,
63 sizeof(log_array)/sizeof(log_array[0]),
64 log_array, NULL, NULL) |
65 translog_flush(commit_lsn));
66
67 DBUG_EXECUTE_IF("maria_sleep_in_commit",
68 {
69 DBUG_PRINT("info", ("maria_sleep_in_commit"));
70 sleep(3);
71 });
72 res|= trnman_commit_trn(trn);
73
74
75 /*
76 Note: if trnman_commit_trn() fails above, we have already
77 written the COMMIT record, so Checkpoint and Recovery will see the
78 transaction as committed.
79 */
80 DBUG_RETURN(res);
81}
82
83
84/**
85 Writes a COMMIT record for a transaciton associated with a file
86
87 @param info Maria handler
88
89 @return Operation status
90 @retval 0 ok
91 @retval # error (disk error or out of memory)
92*/
93
94int maria_commit(MARIA_HA *info)
95{
96 return info->s->now_transactional ? ma_commit(info->trn) : 0;
97}
98
99
100/**
101 Starts a transaction on a file handle
102
103 @param info Maria handler
104
105 @return Operation status
106 @retval 0 ok
107 @retval # Error code.
108
109 @note this can be used only in single-threaded programs (tests),
110 because we create a transaction (trnman_new_trn) with WT_THD=0.
111 XXX it needs to be fixed when we'll start using maria_begin from SQL.
112*/
113
114int maria_begin(MARIA_HA *info)
115{
116 DBUG_ENTER("maria_begin");
117
118 if (info->s->now_transactional)
119 {
120 TRN *trn= trnman_new_trn(0);
121 if (unlikely(!trn))
122 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
123
124 DBUG_PRINT("info", ("TRN set to %p", trn));
125 _ma_set_trn_for_table(info, trn);
126 }
127 DBUG_RETURN(0);
128}
129
130