// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! IoPacket trait encapsulates all the information needed to carry out an IO.
//! It also maintains meta-information about the IO. Each IoPacket maintain time
//! spent in various stages of of IoPacket lifetime. This will help in
//! generating detailed heatmaps (http://www.brendangregg.com/HeatMaps/latency.html)
//! of various aspects of IO

use {
    crate::operations::{OperationType, PipelineStages},
    crate::target::Error,
    std::{
        marker::{Send, Sync},
        ops::Range,
        result::Result,
        time::Instant,
    },
};

pub type IoPacketType = Box<dyn IoPacket + Send + Sync>;

/// This struct maintains monotonically increasing clock time. Though these fields
/// are u128, when writing to disk we write u64 nanos which is sufficient to track
/// single uptime of a system.
#[derive(Clone, Copy)]
pub struct TimeInterval {
    start: Instant,
    end: Instant,
}

impl TimeInterval {
    /// Create a new interval
    pub fn new() -> TimeInterval {
        let start = Instant::now();
        TimeInterval { start: start, end: start }
    }

    /// If creation time and start time are different then explicitly start
    /// measuring time.
    pub fn start(&mut self) {
        self.start = Instant::now();
    }

    /// The start and end time in nanos relative to an arbitrary start_instant.
    pub fn interval_to_u64(&self, start_instant: &Instant) -> (u64, u64) {
        let ustart = self.start.duration_since(*start_instant).as_nanos();
        let uend = self.end.duration_since(*start_instant).as_nanos();
        (ustart as u64, uend as u64)
    }

    /// End measuring the time interval.
    pub fn end(&mut self) {
        self.end = Instant::now();
    }

    /// Duration between create/start and end in nano seconds. This function may
    /// panic if end time is earlier than start time.
    pub fn duration(self) -> u128 {
        self.end.duration_since(self.start).as_nanos()
    }
}

pub enum InternalCommand {
    Abort,
    Exit,
    None,
}

pub trait IoPacket: IoPacketClone {
    /// Function returns type of operation this IoPacket will perform
    fn operation_type(&self) -> OperationType;

    /// Returns IO sequence number of this packet
    fn sequence_number(&self) -> u64;

    /// Starts measuring time for the IO for /stage/
    fn timestamp_stage_start(&mut self, stage: PipelineStages);

    /// Ends measuring time for the IO for /stage/
    fn timestamp_stage_end(&mut self, stage: PipelineStages);

    /// Returns time in nanos spent by this packet in the /stage/
    fn stage_timestamps(&self) -> &[TimeInterval; PipelineStages::stage_count()];

    /// Returns time (in nanos) internal relative to an arbitrary Instant.
    fn interval_to_u64(&self, stage: PipelineStages) -> (u64, u64);

    /// Command to internal command
    fn abort_or_exit(&self) -> InternalCommand {
        match self.operation_type() {
            OperationType::Abort => InternalCommand::Abort,
            OperationType::Exit => InternalCommand::Exit,
            _ => InternalCommand::None,
        }
    }

    /// Returns reference to offset range on which this io packet worked
    fn io_offset_range(&self) -> Range<u64>;

    /// Returns size of the io
    fn io_size(&self) -> u64 {
        let range = self.io_offset_range();
        range.end - range.start
    }

    /// Perform IO
    fn do_io(&mut self);

    /// Return true if the IO is complete. False if it is still pending (for
    /// asynchronous operations).
    fn is_complete(&self) -> bool;

    /// Returns true if verification of IO needs additional IO
    fn verify_needs_io(&self) -> bool;

    /// Generates a verification IoPacket
    fn generate_verify_io(&mut self);

    /// Returns result of the IO command
    fn get_error(&self) -> Result<(), Error>;

    /// Sets error on a IoPacket
    fn set_error(&mut self, error: Error);

    /// Verify the completed IO packet
    fn verify(&mut self, verify_io: &dyn IoPacket) -> bool;

    /// Returns pointer to mutable buffer
    fn buffer_mut(&mut self) -> &mut Vec<u8>;

    /// Returns pointer to buffer
    fn buffer(&mut self) -> &Vec<u8>;
}

/// Make IoPacket clone able for verifier.
pub trait IoPacketClone {
    fn clone_box(&self) -> IoPacketType;
}

impl<T> IoPacketClone for T
where
    T: IoPacket + Send + Sync + Clone + 'static,
{
    fn clone_box(&self) -> IoPacketType {
        Box::new(self.clone())
    }
}

impl Clone for IoPacketType {
    fn clone(&self) -> Self {
        self.clone_box()
    }
}
