1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use tm::xa_error::{XaError, XaResult};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::fmt;
use std::io::{self, Read, Write};
use std::iter::repeat;
#[derive(Clone)]
pub struct XaTransactionId {
format_id: i32,
global_tid: Vec<u8>,
branch_qualifier: Vec<u8>,
}
const MAX_GLOBAL_TRANSACTION_ID_SIZE: usize = 64;
const MAX_BRANCH_QUALIFIER_SIZE: usize = 64;
impl XaTransactionId {
pub fn new(
format_id: i32,
global_tid: Vec<u8>,
branch_qualifier: Vec<u8>,
) -> XaResult<XaTransactionId> {
if format_id < -1 {
Err(XaError::Usage("Bad XA transaction id: invalid format-id"))
} else if global_tid.len() > MAX_GLOBAL_TRANSACTION_ID_SIZE {
Err(XaError::Usage("Invalid global ta id (too long)"))
} else if branch_qualifier.len() > MAX_BRANCH_QUALIFIER_SIZE {
Err(XaError::Usage("Invalid branch_qualifier (too long)"))
} else {
Ok(XaTransactionId {
format_id: format_id,
global_tid: global_tid,
branch_qualifier: branch_qualifier,
})
}
}
pub fn null_ta() -> XaTransactionId {
XaTransactionId {
format_id: -1,
global_tid: vec![],
branch_qualifier: vec![],
}
}
pub fn get_format_id(&self) -> i32 {
self.format_id
}
pub fn get_global_tid(&self) -> &Vec<u8> {
&self.global_tid
}
pub fn get_branch_qualifier(&self) -> &Vec<u8> {
&self.branch_qualifier
}
pub fn as_bytes(&self, padding: bool) -> io::Result<Vec<u8>> {
let mut result = Vec::<u8>::new();
result.write_i32::<LittleEndian>(self.format_id as i32)?;
result.write_i32::<LittleEndian>(self.global_tid.len() as i32)?;
result.write_i32::<LittleEndian>(self.branch_qualifier.len() as i32)?;
result.write_all(&self.global_tid)?;
result.write_all(&self.branch_qualifier)?;
if padding {
let missing = 128 - self.branch_qualifier.len() - self.global_tid.len();
for _ in 0..missing {
result.write_u8(0)?;
}
}
Ok(result)
}
pub fn parse(bytes: &[u8], count: u64, padding: bool) -> XaResult<Vec<XaTransactionId>> {
let mut rdr = io::Cursor::new(bytes);
let mut result = Vec::<XaTransactionId>::new();
for _ in 0..count {
let format_id: i32 = rdr.read_i32::<LittleEndian>()?;
let global_tid_len = rdr.read_i32::<LittleEndian>()? as usize;
let branch_qualifier_len = rdr.read_i32::<LittleEndian>()? as usize;
let mut global_tid: Vec<u8> = repeat(0u8).take(global_tid_len).collect();
rdr.read_exact(&mut global_tid)?;
let mut branch_qualifier: Vec<u8> = repeat(0u8).take(branch_qualifier_len).collect();
rdr.read_exact(&mut branch_qualifier)?;
if padding {
let missing = 128 - branch_qualifier_len - global_tid_len;
for _ in 0..missing {
rdr.read_u8()?;
}
}
result.push(XaTransactionId::new(
format_id,
global_tid,
branch_qualifier,
)?);
}
Ok(result)
}
}
impl fmt::Debug for XaTransactionId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.format_id == -1 {
write!(f, "XaTransactionId {{NULL}}")
} else {
write!(
f,
"XaTransactionId {{format_id: {}, global_tid: {:?}, branch_qualifier: {:?} }}",
self.format_id,
self.global_tid,
self.branch_qualifier
)
}
}
}