mysql_common/binlog/events/
incident_event.rs

1// Copyright (c) 2021 Anatoly Ikorsky
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use std::{
10    borrow::Cow,
11    cmp::min,
12    io::{self},
13};
14
15use saturating::Saturating as S;
16
17use crate::{
18    binlog::{
19        consts::{BinlogVersion, EventType, IncidentType, UnknownIncidentType},
20        BinlogCtx, BinlogEvent, BinlogStruct,
21    },
22    io::ParseBuf,
23    misc::raw::{bytes::U8Bytes, int::*, RawBytes, RawConst},
24    proto::{MyDeserialize, MySerialize},
25};
26
27use super::BinlogEventHeader;
28
29/// Used to log an out of the ordinary event that occurred on the master.
30///
31/// It notifies the slave that something happened on the master that might cause data
32/// to be in an inconsistent state.
33#[derive(Debug, Clone, Eq, PartialEq, Hash)]
34pub struct IncidentEvent<'a> {
35    incident_type: RawConst<LeU16, IncidentType>,
36    message: RawBytes<'a, U8Bytes>,
37}
38
39impl<'a> IncidentEvent<'a> {
40    pub fn new(incident_type: IncidentType, message: impl Into<Cow<'a, [u8]>>) -> Self {
41        Self {
42            incident_type: RawConst::new(incident_type as u16),
43            message: RawBytes::new(message),
44        }
45    }
46
47    /// Returns the `incident_type` value, if it's valid.
48    pub fn incident_type(&self) -> Result<IncidentType, UnknownIncidentType> {
49        self.incident_type.get()
50    }
51
52    /// Returns the raw `message` value.
53    pub fn message_raw(&'a self) -> &'a [u8] {
54        self.message.as_bytes()
55    }
56
57    /// Returns `message` value as a string (lossy converted).
58    pub fn message(&'a self) -> Cow<'a, str> {
59        self.message.as_str()
60    }
61
62    /// Sets the `incident_type` value.
63    pub fn with_incident_type(mut self, incident_type: IncidentType) -> Self {
64        self.incident_type = RawConst::new(incident_type as u16);
65        self
66    }
67
68    /// Sets the `message` value.
69    pub fn with_message(mut self, message: impl Into<Cow<'a, [u8]>>) -> Self {
70        self.message = RawBytes::new(message);
71        self
72    }
73
74    pub fn into_owned(self) -> IncidentEvent<'static> {
75        IncidentEvent {
76            incident_type: self.incident_type,
77            message: self.message.into_owned(),
78        }
79    }
80}
81
82impl<'de> MyDeserialize<'de> for IncidentEvent<'de> {
83    const SIZE: Option<usize> = None;
84    type Ctx = BinlogCtx<'de>;
85
86    fn deserialize(_ctx: Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
87        Ok(Self {
88            incident_type: buf.parse(())?,
89            message: buf.parse(())?,
90        })
91    }
92}
93
94impl MySerialize for IncidentEvent<'_> {
95    fn serialize(&self, buf: &mut Vec<u8>) {
96        self.incident_type.serialize(&mut *buf);
97        self.message.serialize(&mut *buf);
98    }
99}
100
101impl<'a> BinlogEvent<'a> for IncidentEvent<'a> {
102    const EVENT_TYPE: EventType = EventType::INCIDENT_EVENT;
103}
104
105impl<'a> BinlogStruct<'a> for IncidentEvent<'a> {
106    fn len(&self, _version: BinlogVersion) -> usize {
107        let mut len = S(0);
108
109        len += S(2);
110        len += S(1);
111        len += S(min(self.message.0.len(), u8::MAX as usize));
112
113        min(len.0, u32::MAX as usize - BinlogEventHeader::LEN)
114    }
115}