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