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