CUBRID Engine  latest
cas_xa.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * cas_xa.c -
22  */
23 
24 #ident "$Id$"
25 
26 #include "cas_common.h"
27 #include "cas.h"
28 #include "cas_net_buf.h"
29 #include "cas_network.h"
30 #include "cas_log.h"
31 #include "cas_function.h"
32 
33 #include "cas_execute.h"
34 #if !defined(CAS_FOR_ORACLE) && !defined(CAS_FOR_MYSQL)
35 #include "cas_db_inc.h"
36 #endif /* !CAS_FOR_ORACLE && !CAS_FOR_MYSQL */
37 
38 #include "xa.h"
39 #if !defined(CAS_FOR_ORACLE) && !defined(CAS_FOR_MYSQL)
40 #define CAS_SUPPORT_XA
41 #endif /* !CAS_FOR_ORACLE && !CAS_FOR_MYSQL */
42 
43 #define MAX_GTRIDS 100
44 
45 #ifdef CAS_SUPPORT_XA
46 static int net_arg_get_xid (XID * xid, char *buf);
47 static void net_buf_cp_xid (T_NET_BUF * net_buf, XID * xid);
48 static int compare_xid (XID * xid1, XID * xid2);
49 #endif /* CAS_SUPPORT_XA */
50 
51 static bool xa_prepare_flag = false;
52 
55 {
56 #ifdef CAS_SUPPORT_XA
57  XID xid;
58  int err_code, gtrid;
59 
60  if ((argc < 1) || (net_arg_get_xid (&xid, (char *) argv[0]) < 0))
61  {
63  NET_BUF_ERR_SET (net_buf);
64  return FN_KEEP_CONN;
65  }
66 
67  gtrid = db_2pc_start_transaction ();
68  if (gtrid < 0)
69  {
71  NET_BUF_ERR_SET (net_buf);
72  return FN_KEEP_CONN;
73  }
74 
75  err_code = db_set_global_transaction_info (gtrid, (void *) &xid, sizeof (XID));
76  if (err_code < 0)
77  {
79  NET_BUF_ERR_SET (net_buf);
80  return FN_KEEP_CONN;
81  }
82 
83  err_code = db_2pc_prepare_transaction ();
84  if (err_code < 0)
85  {
87  NET_BUF_ERR_SET (net_buf);
88  return FN_KEEP_CONN;
89  }
90 
92 
93  net_buf_cp_int (net_buf, 0, NULL);
94 
95  cas_log_write (0, true, "xa_prepare");
96 #else /* CAS_SUPPORT_XA */
98  NET_BUF_ERR_SET (net_buf);
99 #endif /* CAS_SUPPORT_XA */
100  return FN_KEEP_CONN;
101 }
102 
103 FN_RETURN
105 {
106 #ifdef CAS_SUPPORT_XA
107  int count;
108  int gtrids[MAX_GTRIDS];
109  int i, err_code;
110  XID xid;
111 
112  count = db_2pc_prepared_transactions (gtrids, MAX_GTRIDS);
113  if (count < 0)
114  {
116  NET_BUF_ERR_SET (net_buf);
117  return FN_KEEP_CONN;
118  }
119 
120  net_buf_cp_int (net_buf, count, NULL);
121 
122  for (i = 0; i < count; i++)
123  {
124  err_code = db_get_global_transaction_info (gtrids[i], (void *) &xid, sizeof (XID));
125  if (err_code < 0)
126  {
128  NET_BUF_ERR_SET (net_buf);
129  return FN_KEEP_CONN;
130  }
131  net_buf_cp_xid (net_buf, &xid);
132  }
133 
134  cas_log_write (0, true, "xa_recover");
135 #else /* CAS_SUPPORT_XA */
137  NET_BUF_ERR_SET (net_buf);
138 #endif /* CAS_SUPPORT_XA */
139  return FN_KEEP_CONN;
140 }
141 
142 FN_RETURN
144 {
145 #ifdef CAS_SUPPORT_XA
146  int tran_type;
147  XID xid, tmp_xid;
148  int gtrids[MAX_GTRIDS];
149  int i, err_code, gtrid, count;
150 
151  if ((argc < 2) || (net_arg_get_xid (&xid, (char *) argv[0]) < 0))
152  {
154  NET_BUF_ERR_SET (net_buf);
155  return FN_KEEP_CONN;
156  }
157  net_arg_get_char (tran_type, argv[1]);
158  if (tran_type != CCI_TRAN_COMMIT && tran_type != CCI_TRAN_ROLLBACK)
159  {
161  NET_BUF_ERR_SET (net_buf);
162  return FN_KEEP_CONN;
163  }
164 
165  count = db_2pc_prepared_transactions (gtrids, MAX_GTRIDS);
166  if (count < 0)
167  {
169  NET_BUF_ERR_SET (net_buf);
170  return FN_KEEP_CONN;
171  }
172 
173  for (gtrid = -1, i = 0; i < count; i++)
174  {
175  err_code = db_get_global_transaction_info (gtrids[i], (void *) &tmp_xid, sizeof (XID));
176  if (err_code < 0)
177  {
179  NET_BUF_ERR_SET (net_buf);
180  return FN_KEEP_CONN;
181  }
182  if (compare_xid (&xid, &tmp_xid) == 0)
183  {
184  gtrid = gtrids[i];
185  break;
186  }
187  }
188 
189  if (gtrid >= 0)
190  {
191 #if 0
192  ux_end_tran (CCI_TRAN_ROLLBACK);
193 #endif
194 
195  err_code = db_2pc_attach_transaction (gtrid);
196  if (err_code < 0)
197  {
199  NET_BUF_ERR_SET (net_buf);
200  return FN_KEEP_CONN;
201  }
202 
203  ux_end_tran (tran_type, true);
205  }
206 
207  net_buf_cp_int (net_buf, 0, NULL);
208  cas_log_write (0, true, "xa_end_tran %d", tran_type);
209 #else /* CAS_SUPPORT_XA */
211  NET_BUF_ERR_SET (net_buf);
212 #endif /* CAS_SUPPORT_XA */
213  return FN_CLOSE_CONN;
214 }
215 
216 #ifdef CAS_SUPPORT_XA
217 static int
218 net_arg_get_xid (XID * xid, char *buf)
219 {
220  int data_size;
221  int i, id[3];
222 
223  memset (xid, 0, sizeof (XID));
224 
225  memcpy (&data_size, buf, 4);
226  data_size = ntohl (data_size);
227  buf += 4;
228 
229  for (i = 0; i < 3; i++)
230  {
231  if (data_size < 4)
232  return -1;
233  memcpy (&id[i], buf, 4);
234  id[i] = ntohl (id[i]);
235  buf += 4;
236  data_size -= 4;
237  }
238 
239  if (data_size < id[1] + id[2])
240  return -1;
241 
242  xid->formatID = id[0];
243  xid->gtrid_length = id[1];
244  xid->bqual_length = id[2];
245  memcpy (xid->data, buf, id[1] + id[2]);
246  return 0;
247 }
248 
249 static void
250 net_buf_cp_xid (T_NET_BUF * net_buf, XID * xid)
251 {
252  net_buf_cp_int (net_buf, 12 + xid->gtrid_length + xid->bqual_length, NULL);
253  net_buf_cp_int (net_buf, xid->formatID, NULL);
254  net_buf_cp_int (net_buf, xid->gtrid_length, NULL);
255  net_buf_cp_int (net_buf, xid->bqual_length, NULL);
256  net_buf_cp_str (net_buf, xid->data, xid->gtrid_length + xid->bqual_length);
257 }
258 
259 static int
260 compare_xid (XID * xid1, XID * xid2)
261 {
262  if (xid1->formatID != xid2->formatID)
263  return -1;
264  if (xid1->gtrid_length != xid2->gtrid_length)
265  return -1;
266  if (xid1->bqual_length != xid2->bqual_length)
267  return -1;
268  return (memcmp (xid1->data, xid2->data, xid1->gtrid_length + xid1->bqual_length));
269 }
270 #endif /* CAS_SUPPORT_XA */
271 
272 bool
274 {
275  return xa_prepare_flag;
276 }
277 
278 void
280 {
281  xa_prepare_flag = true;
282 }
283 
284 void
286 {
287  xa_prepare_flag = false;
288 }
#define NET_BUF_ERR_SET(NET_BUF)
Definition: cas_execute.h:55
int SOCKET
Definition: porting.h:482
int net_buf_cp_str(T_NET_BUF *net_buf, const char *buf, int size)
Definition: cas_net_buf.c:110
void unset_xa_prepare_flag(void)
Definition: cas_xa.c:285
int argc
Definition: dynamic_load.c:951
long gtrid_length
Definition: xa.h:41
FN_RETURN
Definition: cas_function.h:31
#define MAX_GTRIDS
Definition: cas_xa.c:43
int db_2pc_prepared_transactions(int gtrids[], int size)
Definition: db_admin.c:1373
long bqual_length
Definition: xa.h:42
static bool xa_prepare_flag
Definition: cas_xa.c:51
char data[XIDDATASIZE]
Definition: xa.h:43
int db_get_global_transaction_info(int global_transaction_id, void *buffer, int size)
Definition: db_admin.c:1295
int net_buf_cp_int(T_NET_BUF *net_buf, int value, int *begin_offset)
Definition: cas_net_buf.c:126
FN_RETURN fn_xa_prepare(SOCKET sock_fd, int argc, void **argv, T_NET_BUF *net_buf, T_REQ_INFO *req_info)
Definition: cas_xa.c:54
#define CAS_ERROR_INDICATOR
Definition: cas.h:39
void set_xa_prepare_flag(void)
Definition: cas_xa.c:279
#define NULL
Definition: freelistheap.h:34
Definition: xa.h:38
FN_RETURN fn_xa_end_tran(SOCKET sock_fd, int argc, void **argv, T_NET_BUF *net_buf, T_REQ_INFO *req_info)
Definition: cas_xa.c:143
long formatID
Definition: xa.h:40
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int db_2pc_attach_transaction(int global_transaction_id)
Definition: db_admin.c:1403
bool is_xa_prepared(void)
Definition: cas_xa.c:273
FN_RETURN fn_xa_recover(SOCKET sock_fd, int argc, void **argv, T_NET_BUF *net_buf, T_REQ_INFO *req_info)
Definition: cas_xa.c:104
int db_2pc_prepare_transaction(void)
Definition: db_admin.c:1351
static void net_buf_cp_xid(T_NET_BUF *net_buf, XID *xid)
Definition: cas_xa.c:250
const char ** argv
Definition: dynamic_load.c:952
void cas_log_write(unsigned int seq_num, bool unit_start, const char *fmt,...)
Definition: cas_log.c:506
int db_set_global_transaction_info(int global_transaction_id, void *info, int size)
Definition: db_admin.c:1262
#define ERROR_INFO_SET(ERR_CODE, ERR_INDICATOR)
Definition: cas_execute.h:49
static SOCKET sock_fd
Definition: broker.c:300
#define DBMS_ERROR_INDICATOR
Definition: cas.h:40
int i
Definition: dynamic_load.c:954
Definition: cas.h:73
int ux_end_tran(int tran_type, bool reset_con_status)
Definition: cas_execute.c:984
unsigned int ntohl(unsigned int from)
static int net_arg_get_xid(XID *xid, char *buf)
Definition: cas_xa.c:218
static T_REQ_INFO req_info
Definition: cas.c:333
static int compare_xid(XID *xid1, XID *xid2)
Definition: cas_xa.c:260
int db_2pc_start_transaction(void)
Definition: db_admin.c:1327
#define net_arg_get_char(value, arg)
Definition: cas_net_buf.h:146