<commit_before>use Configuration;
#[cfg(feature = "unstable")]
use future::{Future, RayonFuture};
use latch::LockLatch;
#[allow(unused_imports)]
use log::Event::*;
use job::StackJob;
use join;
use {scope, Scope};
#[cfg(feature = "unstable")]
use spawn;
use std::sync::Arc;
use std::error::Error;
use registry::{Registry, WorkerThread};

mod test;
/// # ThreadPool
///
/// The [`ThreadPool`] struct represents a user created [thread-pool]. [`ThreadPool::new()`]
/// takes a [`Configuration`] struct that you can use to specify the number and/or
/// names of threads in the pool. You can then execute functions explicitly within
/// this [`ThreadPool`] using [`ThreadPool::install()`]. By contrast, top level
/// rayon functions (like `join()`)  will execute implicitly within the current thread-pool.
///
///
/// ## Creating a ThreadPool
///
/// ```rust
///    # use rayon_core as rayon;
///
///    let pool = rayon::ThreadPool::new(rayon::Configuration::new().num_threads(8)).unwrap();
/// ```
///
/// [`install()`] executes a closure in one of the `ThreadPool`'s threads. In addition,
/// any other rayon operations called inside of `install()` will also execute in the
/// context of the `ThreadPool`.
///
/// When the `ThreadPool` is dropped, that's a signal for the threads it manages to terminate,
/// they will complete executing any remaining work that you have spawned, and automatically
/// terminate.
///
///
/// [thread-pool]: https://en.wikipedia.org/wiki/Thread_pool
/// [`ThreadPool`]: struct.ThreadPool.html
/// [`ThreadPool::new()`]: struct.ThreadPool.html#method.new
/// [`Configuration`]: struct.Configuration.html
/// [`ThreadPool::install()`]: struct.ThreadPool.html#method.install
pub struct ThreadPool {
    registry: Arc<Registry>,
}

impl ThreadPool {
    /// Constructs a new thread pool with the given configuration. If
    /// the configuration is not valid, returns a suitable `Err`
    /// result.  See `InitError` for more details.
    pub fn new(configuration: Configuration) -> Result<ThreadPool, Box<Error>> {
        let registry = try!(Registry::new(configuration));
        Ok(ThreadPool { registry: registry })
    }

    /// Returns a handle to the global thread pool. This is the pool
    /// that Rayon will use by default when you perform a `join()` or
    /// `scope()` operation, if no other thread-pool is installed. If
    /// no global thread-pool has yet been started when this function
    /// is called, then the global thread-pool will be created (with
    /// the default configuration). If you wish to configure the
    /// global thread-pool differently, then you can use [the
    /// `rayon::initialize()` function][f] to do so.
    ///
    /// [f]: fn.initialize.html
    #[cfg(feature = "unstable")]
    pub fn global() -> &'static Arc<ThreadPool> {
        lazy_static! {
            static ref DEFAULT_THREAD_POOL: Arc<ThreadPool> =
                Arc::new(ThreadPool { registry: Registry::global() });
        }

        &DEFAULT_THREAD_POOL
    }

    /// Executes `op` within the threadpool. Any attempts to use
    /// `join`, `scope`, or parallel iterators will then operate
    /// within that threadpool.
    ///
    /// # Warning: thread-local data
    ///
    /// Because `op` is executing within the Rayon thread-pool,
    /// thread-local data from the current thread will not be
    /// accessible.
    ///
    /// # Panics
    ///
    /// If `op` should panic, that panic will be propagated.
    ///
    /// ## Using `install()`
    ///
    /// ```rust
    ///    # use rayon_core as rayon;
    ///    fn main() {
    ///         let pool = rayon::ThreadPool::new(rayon::Configuration::new().num_threads(8)).unwrap();
    ///         pool.install(|| {
    ///                          let n = fib(20);
    ///                          println!("{}", n);
    ///                      });
    ///    }
    ///
    ///    fn fib(n: usize) -> usize {
    ///         if n == 0 || n == 1 {
    ///             return n;
    ///         }
    ///         let (a, b) = rayon::join(|| fib(n - 1), || fib(n - 2)); // runs inside of `pool`
    ///         return a + b;
    ///     }
    /// ```
    pub fn install<OP, R>(&self, op: OP) -> R
        where OP: FnOnce() -> R + Send
    {
        unsafe {
            let job_a = StackJob::new(op, LockLatch::new());
            self.registry.inject(&[job_a.as_job_ref()]);
            job_a.latch.wait();
            job_a.into_result()
        }
    }

    /// Returns the (current) number of threads in the thread pool.
    ///
    /// ### Future compatibility note
    ///
    /// Note that unless this thread-pool was created with a
    /// configuration that specifies the number of threads, then this
    /// number may vary over time in future versions (see [the
    /// `num_threads()` method for details][snt]).
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_num_threads(&self) -> usize {
        self.registry.num_threads()
    }

    /// If called from a Rayon worker thread in this thread-pool,
    /// returns the index of that thread; if not called from a Rayon
    /// thread, or called from a Rayon thread that belongs to a
    /// different thread-pool, returns `None`.
    ///
    /// The index for a given thread will not change over the thread's
    /// lifetime. However, multiple threads may share the same index if
    /// they are in distinct thread-pools.
    ///
    /// ### Future compatibility note
    ///
    /// Currently, every thread-pool (including the global
    /// thread-pool) has a fixed number of threads, but this may
    /// change in future Rayon versions (see [the `num_threads()` method
    /// for details][snt]). In that case, the index for a
    /// thread would not change during its lifetime, but thread
    /// indices may wind up being reused if threads are terminated and
    /// restarted.
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_thread_index(&self) -> Option<usize> {
        unsafe {
            let curr = WorkerThread::current();
            if curr.is_null() {
                None
            } else if (*curr).registry().id() != self.registry.id() {
                None
            } else {
                Some((*curr).index())
            }
        }
    }

    /// Execute `oper_a` and `oper_b` in the thread-pool and return
    /// the results. Equivalent to `self.install(|| join(oper_a,
    /// oper_b))`.
    #[cfg(feature = "unstable")]
    pub fn join<A, B, RA, RB>(&self, oper_a: A, oper_b: B) -> (RA, RB)
        where A: FnOnce() -> RA + Send,
              B: FnOnce() -> RB + Send,
              RA: Send,
              RB: Send
    {
        self.install(|| join(oper_a, oper_b))
    }

    /// Creates a scope that executes within this thread-pool.
    /// Equivalent to `self.install(|| scope(...))`.
    ///
    /// See also: [the `scope()` function][scope].
    ///
    /// [scope]: fn.scope.html
    #[cfg(feature = "unstable")]
    pub fn scope<'scope, OP, R>(&self, op: OP) -> R
        where OP: for<'s> FnOnce(&'s Scope<'scope>) -> R + 'scope + Send, R: Send
    {
        self.install(|| scope(op))
    }

    /// Spawns an asynchronous task in this thread-pool. This task will
    /// run in the implicit, global scope, which means that it may outlast
    /// the current stack frame -- therefore, it cannot capture any references
    /// onto the stack (you will likely need a `move` closure).
    ///
    /// See the [`spawn()` method defined on scopes][spawn] for more details.
    ///
    /// [spawn]: struct.Scope.html#method.spawn
    #[cfg(feature = "unstable")]
    pub fn spawn<OP>(&self, op: OP)
        where OP: FnOnce() + Send + 'static
    {
        // We assert that `self.registry` has not terminated.
        unsafe { spawn::spawn_in(op, &self.registry) }
    }

    /// Spawns an asynchronous future in the thread pool. `spawn_future()` will inject
    /// jobs into the threadpool that are not tied to your current stack frame. This means
    /// `ThreadPool`'s `spawn` methods are not scoped. As a result, it cannot access data
    /// owned by the stack.
    ///
    /// `spawn_future()` returns a `RayonFuture<F::Item, F::Error>`, allowing you to chain
    /// multiple jobs togther.
    ///
    /// ## Using `spawn_future()`
    ///
    /// ```rust
    ///    # extern crate rayon_core as rayon;
    ///    extern crate futures;
    ///
    ///    use futures::{future, Future};
    ///    use std::sync::{Arc, Mutex};
    ///    # fn main() {
    ///    let data = Arc::new(Mutex::new(String::from("Hello,")));
    ///    let pool = rayon::ThreadPool::new(rayon::Configuration::new().num_threads(8)).unwrap();
    ///
    ///    let a = pool.spawn_future(future::lazy({
    ///                                               let data = data.clone();
    ///                                               move || Ok::<_, ()>(data)
    ///                                           }));
    ///    let b = pool.spawn_future(a.map(|data| {
    ///                                               let mut v = data.lock().unwrap();
    ///                                               v.push_str(" world!");
    ///                                           }));
    ///    let () = b.wait().unwrap();
    ///    println!("{:?}", &data.lock().unwrap()[..]);
    ///    // prints: "Hello, world!"
    ///    # }
    /// ```
    ///
    /// See the [`spawn_future()` method defined on scopes][spawn_future] for more details.
    ///
    /// [spawn_future]: struct.Scope.html#method.spawn_future
    #[cfg(feature = "unstable")]
    pub fn spawn_future<F>(&self, future: F) -> RayonFuture<F::Item, F::Error>
        where F: Future + Send + 'static
    {
        // We assert that `self.registry` has not yet terminated.
        unsafe { spawn::spawn_future_in(future, self.registry.clone()) }
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        self.registry.terminate();
    }
}

<commit_msg>Threadpool doc requested changes<commit_after>use Configuration;
#[cfg(feature = "unstable")]
use future::{Future, RayonFuture};
use latch::LockLatch;
#[allow(unused_imports)]
use log::Event::*;
use job::StackJob;
use join;
use {scope, Scope};
#[cfg(feature = "unstable")]
use spawn;
use std::sync::Arc;
use std::error::Error;
use registry::{Registry, WorkerThread};

mod test;
/// # ThreadPool
///
/// The [`ThreadPool`] struct represents a user created [thread-pool]. [`ThreadPool::new()`]
/// takes a [`Configuration`] struct that you can use to specify the number and/or
/// names of threads in the pool. You can then execute functions explicitly within
/// this [`ThreadPool`] using [`ThreadPool::install()`]. By contrast, top level
/// rayon functions (like `join()`)  will execute implicitly within the current thread-pool.
///
///
/// ## Creating a ThreadPool
///
/// ```rust
///    # use rayon_core as rayon;
///
///    let pool = rayon::ThreadPool::new(rayon::Configuration::new().num_threads(8)).unwrap();
/// ```
///
/// [`install()`] executes a closure in one of the `ThreadPool`'s threads. In addition,
/// any other rayon operations called inside of `install()` will also execute in the
/// context of the `ThreadPool`.
///
/// When the `ThreadPool` is dropped, that's a signal for the threads it manages to terminate,
/// they will complete executing any remaining work that you have spawned, and automatically
/// terminate.
///
///
/// [thread-pool]: https://en.wikipedia.org/wiki/Thread_pool
/// [`ThreadPool`]: struct.ThreadPool.html
/// [`ThreadPool::new()`]: struct.ThreadPool.html#method.new
/// [`Configuration`]: struct.Configuration.html
/// [`ThreadPool::install()`]: struct.ThreadPool.html#method.install
pub struct ThreadPool {
    registry: Arc<Registry>,
}

impl ThreadPool {
    /// Constructs a new thread pool with the given configuration. If
    /// the configuration is not valid, returns a suitable `Err`
    /// result.  See `InitError` for more details.
    pub fn new(configuration: Configuration) -> Result<ThreadPool, Box<Error>> {
        let registry = try!(Registry::new(configuration));
        Ok(ThreadPool { registry: registry })
    }

    /// Returns a handle to the global thread pool. This is the pool
    /// that Rayon will use by default when you perform a `join()` or
    /// `scope()` operation, if no other thread-pool is installed. If
    /// no global thread-pool has yet been started when this function
    /// is called, then the global thread-pool will be created (with
    /// the default configuration). If you wish to configure the
    /// global thread-pool differently, then you can use [the
    /// `rayon::initialize()` function][f] to do so.
    ///
    /// [f]: fn.initialize.html
    #[cfg(feature = "unstable")]
    pub fn global() -> &'static Arc<ThreadPool> {
        lazy_static! {
            static ref DEFAULT_THREAD_POOL: Arc<ThreadPool> =
                Arc::new(ThreadPool { registry: Registry::global() });
        }

        &DEFAULT_THREAD_POOL
    }

    /// Executes `op` within the threadpool. Any attempts to use
    /// `join`, `scope`, or parallel iterators will then operate
    /// within that threadpool.
    ///
    /// # Warning: thread-local data
    ///
    /// Because `op` is executing within the Rayon thread-pool,
    /// thread-local data from the current thread will not be
    /// accessible.
    ///
    /// # Panics
    ///
    /// If `op` should panic, that panic will be propagated.
    ///
    /// ## Using `install()`
    ///
    /// ```rust
    ///    # use rayon_core as rayon;
    ///    fn main() {
    ///         let pool = rayon::ThreadPool::new(rayon::Configuration::new().num_threads(8)).unwrap();
    ///         let n = pool.install(|| fib(20));
    ///         println!("{}", n);
    ///    }
    ///
    ///    fn fib(n: usize) -> usize {
    ///         if n == 0 || n == 1 {
    ///             return n;
    ///         }
    ///         let (a, b) = rayon::join(|| fib(n - 1), || fib(n - 2)); // runs inside of `pool`
    ///         return a + b;
    ///     }
    /// ```
    pub fn install<OP, R>(&self, op: OP) -> R
        where OP: FnOnce() -> R + Send
    {
        unsafe {
            let job_a = StackJob::new(op, LockLatch::new());
            self.registry.inject(&[job_a.as_job_ref()]);
            job_a.latch.wait();
            job_a.into_result()
        }
    }

    /// Returns the (current) number of threads in the thread pool.
    ///
    /// ### Future compatibility note
    ///
    /// Note that unless this thread-pool was created with a
    /// configuration that specifies the number of threads, then this
    /// number may vary over time in future versions (see [the
    /// `num_threads()` method for details][snt]).
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_num_threads(&self) -> usize {
        self.registry.num_threads()
    }

    /// If called from a Rayon worker thread in this thread-pool,
    /// returns the index of that thread; if not called from a Rayon
    /// thread, or called from a Rayon thread that belongs to a
    /// different thread-pool, returns `None`.
    ///
    /// The index for a given thread will not change over the thread's
    /// lifetime. However, multiple threads may share the same index if
    /// they are in distinct thread-pools.
    ///
    /// ### Future compatibility note
    ///
    /// Currently, every thread-pool (including the global
    /// thread-pool) has a fixed number of threads, but this may
    /// change in future Rayon versions (see [the `num_threads()` method
    /// for details][snt]). In that case, the index for a
    /// thread would not change during its lifetime, but thread
    /// indices may wind up being reused if threads are terminated and
    /// restarted.
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_thread_index(&self) -> Option<usize> {
        unsafe {
            let curr = WorkerThread::current();
            if curr.is_null() {
                None
            } else if (*curr).registry().id() != self.registry.id() {
                None
            } else {
                Some((*curr).index())
            }
        }
    }

    /// Execute `oper_a` and `oper_b` in the thread-pool and return
    /// the results. Equivalent to `self.install(|| join(oper_a,
    /// oper_b))`.
    #[cfg(feature = "unstable")]
    pub fn join<A, B, RA, RB>(&self, oper_a: A, oper_b: B) -> (RA, RB)
        where A: FnOnce() -> RA + Send,
              B: FnOnce() -> RB + Send,
              RA: Send,
              RB: Send
    {
        self.install(|| join(oper_a, oper_b))
    }

    /// Creates a scope that executes within this thread-pool.
    /// Equivalent to `self.install(|| scope(...))`.
    ///
    /// See also: [the `scope()` function][scope].
    ///
    /// [scope]: fn.scope.html
    #[cfg(feature = "unstable")]
    pub fn scope<'scope, OP, R>(&self, op: OP) -> R
        where OP: for<'s> FnOnce(&'s Scope<'scope>) -> R + 'scope + Send, R: Send
    {
        self.install(|| scope(op))
    }

    /// Spawns an asynchronous task in this thread-pool. This task will
    /// run in the implicit, global scope, which means that it may outlast
    /// the current stack frame -- therefore, it cannot capture any references
    /// onto the stack (you will likely need a `move` closure).
    ///
    /// See also: [the `spawn()` function defined on scopes][spawn].
    ///
    /// [spawn]: struct.Scope.html#method.spawn
    #[cfg(feature = "unstable")]
    pub fn spawn<OP>(&self, op: OP)
        where OP: FnOnce() + Send + 'static
    {
        // We assert that `self.registry` has not terminated.
        unsafe { spawn::spawn_in(op, &self.registry) }
    }

    /// Spawns an asynchronous future in the thread pool. `spawn_future()` will inject
    /// jobs into the threadpool that are not tied to your current stack frame. This means
    /// `ThreadPool`'s `spawn` methods are not scoped. As a result, it cannot access data
    /// owned by the stack.
    ///
    /// `spawn_future()` returns a `RayonFuture<F::Item, F::Error>`, allowing you to chain
    /// multiple jobs togther.
    ///
    /// ## Using `spawn_future()`
    ///
    /// ```rust
    ///    # extern crate rayon_core as rayon;
    ///    extern crate futures;
    ///    use futures::{future, Future};
    ///    # fn main() {
    ///
    ///    let pool = rayon::ThreadPool::new(rayon::Configuration::new().num_threads(8)).unwrap();
    ///
    ///    let a = pool.spawn_future(future::lazy(move || Ok::<_, ()>(format!("Hello, "))));
    ///    let b = pool.spawn_future(a.map(|mut data| {
    ///                                        data.push_str("world");
    ///                                        data
    ///                                    }));
    ///    let result = b.wait().unwrap(); // `Err` is impossible, so use `unwrap()` here
    ///    println!("{:?}", result); // prints: "Hello, world!"
    ///    # }
    /// ```
    ///
    /// See also: [the `spawn_future()` function defined on scopes][spawn_future].
    ///
    /// [spawn_future]: struct.Scope.html#method.spawn_future
    #[cfg(feature = "unstable")]
    pub fn spawn_future<F>(&self, future: F) -> RayonFuture<F::Item, F::Error>
        where F: Future + Send + 'static
    {
        // We assert that `self.registry` has not yet terminated.
        unsafe { spawn::spawn_future_in(future, self.registry.clone()) }
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        self.registry.terminate();
    }
}

<|endoftext|>


<commit_before>#![no_std]

use kata_io as io;

// C interface to external UART driver.
extern "C" {
    static rx_dataport: *mut cty::c_char;
    static tx_dataport: *mut cty::c_char;
    fn uart_rx(n: cty::size_t);
    fn uart_tx(n: cty::size_t);
}

pub struct Rx {}

impl io::Read for Rx {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
        unsafe {
            uart_rx(buf.len());
            let port = core::slice::from_raw_parts(rx_dataport, buf.len());
            buf.copy_from_slice(&port);
        }
        Ok(buf.len())
    }
}

pub struct Tx {}

impl io::Write for Tx {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        unsafe {
            let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
            port.copy_from_slice(buf);
            uart_tx(buf.len());
        }
        Ok(buf.len())
    }
}
<commit_msg>kata-uart-client: use correct type for dataports<commit_after>#![no_std]

use kata_io as io;

// C interface to external UART driver.
extern "C" {
    static rx_dataport: *mut cty::c_uchar;
    static tx_dataport: *mut cty::c_uchar;
    fn uart_rx(n: cty::size_t);
    fn uart_tx(n: cty::size_t);
}

pub struct Rx {}

impl io::Read for Rx {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
        unsafe {
            uart_rx(buf.len());
            let port = core::slice::from_raw_parts(rx_dataport, buf.len());
            buf.copy_from_slice(&port);
        }
        Ok(buf.len())
    }
}

pub struct Tx {}

impl io::Write for Tx {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        unsafe {
            let port = core::slice::from_raw_parts_mut(tx_dataport, buf.len());
            port.copy_from_slice(buf);
            uart_tx(buf.len());
        }
        Ok(buf.len())
    }
}
<|endoftext|>


<commit_before>//! Implementations of the MessageEventContent and StateEventContent derive macro.

use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{
    parse::{Parse, ParseStream},
    DeriveInput, Ident, LitStr, Token,
};

mod kw {
    // This `content` field is kept when the event is redacted.
    syn::custom_keyword!(skip_redaction);
    // Do not emit any redacted event code.
    syn::custom_keyword!(custom_redacted);
}

/// Parses attributes for `*EventContent` derives.
///
/// `#[ruma_event(type = "m.room.alias")]`
#[derive(Eq, PartialEq)]
enum EventMeta {
    /// Variant holds the "m.whatever" event type.
    Type(LitStr),

    /// Fields marked with `#[ruma_event(skip_redaction)]` are kept when the event is
    /// redacted.
    SkipRedacted,

    /// This attribute signals that the events redacted form is manually implemented and should
    /// not be generated.
    CustomRedacted,
}

impl EventMeta {
    fn get_event_type(&self) -> Option<&LitStr> {
        if let Self::Type(lit) = self {
            Some(lit)
        } else {
            None
        }
    }
}

impl Parse for EventMeta {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        if input.parse::<Token![type]>().is_ok() {
            input.parse::<Token![=]>()?;
            Ok(EventMeta::Type(input.parse::<LitStr>()?))
        } else if input.parse::<kw::skip_redaction>().is_ok() {
            Ok(EventMeta::SkipRedacted)
        } else if input.parse::<kw::custom_redacted>().is_ok() {
            Ok(EventMeta::CustomRedacted)
        } else {
            Err(syn::Error::new(input.span(), "not a recognized `ruma_event` attribute"))
        }
    }
}

struct MetaAttrs(Vec<EventMeta>);

impl MetaAttrs {
    fn is_custom(&self) -> bool {
        self.0.iter().any(|a| a == &EventMeta::CustomRedacted)
    }

    fn get_event_type(&self) -> Option<&LitStr> {
        self.0.iter().find_map(|a| a.get_event_type())
    }
}

impl Parse for MetaAttrs {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let attrs = syn::punctuated::Punctuated::<EventMeta, Token![,]>::parse_terminated(input)?;
        Ok(Self(attrs.into_iter().collect()))
    }
}

/// Create an `EventContent` implementation for a struct.
pub fn expand_event_content(
    input: &DeriveInput,
    emit_redacted: bool,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
    let serde = quote! { #ruma_events::exports::serde };
    let serde_json = quote! { #ruma_events::exports::serde_json };

    let ident = &input.ident;

    let content_attr = input
        .attrs
        .iter()
        .filter(|attr| attr.path.is_ident("ruma_event"))
        .map(|attr| attr.parse_args::<MetaAttrs>())
        .collect::<syn::Result<Vec<_>>>()?;

    let event_type = content_attr.iter().find_map(|a| a.get_event_type()).ok_or_else(|| {
        let msg = "no event type attribute found, \
            add `#[ruma_event(type = \"any.room.event\")]` \
            below the event content derive";

        syn::Error::new(Span::call_site(), msg)
    })?;

    let redacted = if emit_redacted && needs_redacted(&content_attr) {
        let doc = format!("The payload for a redacted `{}`", ident);
        let redacted_ident = format_ident!("Redacted{}", ident);
        let kept_redacted_fields = if let syn::Data::Struct(syn::DataStruct {
            fields: syn::Fields::Named(syn::FieldsNamed { named, .. }),
            ..
        }) = &input.data
        {
            // this is to validate the `#[ruma_event(skip_redaction)]` attribute
            named
                .iter()
                .flat_map(|f| &f.attrs)
                .filter(|a| a.path.is_ident("ruma_event"))
                .find_map(|a| {
                    if let Err(e) = a.parse_args::<EventMeta>() {
                        Some(Err(e))
                    } else {
                        None
                    }
                })
                .unwrap_or(Ok(()))?;

            let mut fields = named
                .iter()
                .filter(|f| {
                    f.attrs.iter().find_map(|a| a.parse_args::<EventMeta>().ok())
                        == Some(EventMeta::SkipRedacted)
                })
                .cloned()
                .collect::<Vec<_>>();

            // don't re-emit our `ruma_event` attributes
            for f in &mut fields {
                f.attrs.retain(|a| !a.path.is_ident("ruma_event"));
            }
            fields
        } else {
            vec![]
        };
        let redaction_struct_fields = kept_redacted_fields.iter().flat_map(|f| &f.ident);

        // redacted_fields allows one to declare an empty redacted event without braces,
        // otherwise `RedactedWhateverEventContent {}` is needed.
        // The redacted_return is used in `EventContent::redacted` which only returns
        // zero sized types (unit structs).
        let (redacted_fields, redacted_return) = if kept_redacted_fields.is_empty() {
            (quote! { ; }, quote! { Ok(#redacted_ident {}) })
        } else {
            (
                quote! {
                    { #( #kept_redacted_fields, )* }
                },
                quote! {
                    Err(#serde::de::Error::custom(
                        format!("this redacted event has fields that cannot be constructed")
                    ))
                },
            )
        };

        let has_deserialize_fields = if kept_redacted_fields.is_empty() {
            quote! { #ruma_events::HasDeserializeFields::False }
        } else {
            quote! { #ruma_events::HasDeserializeFields::True }
        };

        let has_serialize_fields = if kept_redacted_fields.is_empty() {
            quote! { false }
        } else {
            quote! { true }
        };

        let redacted_event_content =
            generate_event_content_impl(&redacted_ident, event_type, ruma_events);

        quote! {
            // this is the non redacted event content's impl
            #[automatically_derived]
            impl #ident {
                /// Transforms the full event content into a redacted content according to spec.
                pub fn redact(self, version: #ruma_identifiers::RoomVersionId) -> #redacted_ident {
                    #redacted_ident {
                        #( #redaction_struct_fields: self.#redaction_struct_fields, )*
                    }
                }
            }

            #[doc = #doc]
            #[derive(Clone, Debug, #serde::Deserialize, #serde::Serialize)]
            pub struct #redacted_ident #redacted_fields

            #redacted_event_content

            #[automatically_derived]
            impl #ruma_events::RedactedEventContent for #redacted_ident {
                fn empty(ev_type: &str) -> Result<Self, #serde_json::Error> {
                    if ev_type != #event_type {
                        return Err(#serde::de::Error::custom(
                            format!("expected event type `{}`, found `{}`", #event_type, ev_type)
                        ));
                    }

                    #redacted_return
                }

                fn has_serialize_fields(&self) -> bool {
                    #has_serialize_fields
                }

                fn has_deserialize_fields() -> #ruma_events::HasDeserializeFields {
                    #has_deserialize_fields
                }
            }
        }
    } else {
        TokenStream::new()
    };

    let event_content = generate_event_content_impl(ident, event_type, ruma_events);

    Ok(quote! {
        #event_content

        #redacted
    })
}

/// Create a `BasicEventContent` implementation for a struct
pub fn expand_basic_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let event_content_impl = expand_event_content(input, false, ruma_events)?;

    Ok(quote! {
        #event_content_impl

        #[automatically_derived]
        impl #ruma_events::BasicEventContent for #ident {}
    })
}

/// Create a `EphemeralRoomEventContent` implementation for a struct
pub fn expand_ephemeral_room_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let event_content_impl = expand_event_content(input, false, ruma_events)?;

    Ok(quote! {
        #event_content_impl

        #[automatically_derived]
        impl #ruma_events::EphemeralRoomEventContent for #ident {}
    })
}

/// Create a `RoomEventContent` implementation for a struct.
pub fn expand_room_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let event_content_impl = expand_event_content(input, true, ruma_events)?;

    Ok(quote! {
        #event_content_impl

        #[automatically_derived]
        impl #ruma_events::RoomEventContent for #ident {}
    })
}

/// Create a `MessageEventContent` implementation for a struct
pub fn expand_message_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let room_ev_content = expand_room_event_content(input, ruma_events)?;

    let redacted_marker_trait = if needs_redacted_from_input(input) {
        let ident = format_ident!("Redacted{}", &ident);
        quote! {
            #[automatically_derived]
            impl #ruma_events::RedactedMessageEventContent for #ident {}
        }
    } else {
        TokenStream::new()
    };

    Ok(quote! {
        #room_ev_content

        #[automatically_derived]
        impl #ruma_events::MessageEventContent for #ident {}

        #redacted_marker_trait
    })
}

/// Create a `StateEventContent` implementation for a struct
pub fn expand_state_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let room_ev_content = expand_room_event_content(input, ruma_events)?;

    let redacted_marker_trait = if needs_redacted_from_input(input) {
        let ident = format_ident!("Redacted{}", input.ident);
        quote! {
            #[automatically_derived]
            impl #ruma_events::RedactedStateEventContent for #ident {}
        }
    } else {
        TokenStream::new()
    };

    Ok(quote! {
        #room_ev_content

        #[automatically_derived]
        impl #ruma_events::StateEventContent for #ident {}

        #redacted_marker_trait
    })
}

fn generate_event_content_impl(
    ident: &Ident,
    event_type: &LitStr,
    ruma_events: &TokenStream,
) -> TokenStream {
    let serde = quote! { #ruma_events::exports::serde };
    let serde_json = quote! { #ruma_events::exports::serde_json };

    quote! {
        #[automatically_derived]
        impl #ruma_events::EventContent for #ident {
            fn event_type(&self) -> &str {
                #event_type
            }

            fn from_parts(
                ev_type: &str,
                content: Box<#serde_json::value::RawValue>
            ) -> Result<Self, #serde_json::Error> {
                if ev_type != #event_type {
                    return Err(#serde::de::Error::custom(
                        format!("expected event type `{}`, found `{}`", #event_type, ev_type)
                    ));
                }

                #serde_json::from_str(content.get())
            }
        }
    }
}

fn needs_redacted(input: &[MetaAttrs]) -> bool {
    // `is_custom` means that the content struct does not need a generated
    // redacted struct also. If no `custom_redacted` attrs are found the content
    // needs a redacted struct generated.
    !input.iter().any(|a| a.is_custom())
}

fn needs_redacted_from_input(input: &DeriveInput) -> bool {
    !input.attrs.iter().flat_map(|a| a.parse_args::<MetaAttrs>().ok()).any(|a| a.is_custom())
}
<commit_msg>Stop relying on features activated through dev-dependencies<commit_after>//! Implementations of the MessageEventContent and StateEventContent derive macro.

use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{
    parse::{Parse, ParseStream},
    DeriveInput, Ident, LitStr, Token,
};

mod kw {
    // This `content` field is kept when the event is redacted.
    syn::custom_keyword!(skip_redaction);
    // Do not emit any redacted event code.
    syn::custom_keyword!(custom_redacted);
}

/// Parses attributes for `*EventContent` derives.
///
/// `#[ruma_event(type = "m.room.alias")]`
enum EventMeta {
    /// Variant holds the "m.whatever" event type.
    Type(LitStr),

    /// Fields marked with `#[ruma_event(skip_redaction)]` are kept when the event is
    /// redacted.
    SkipRedacted,

    /// This attribute signals that the events redacted form is manually implemented and should
    /// not be generated.
    CustomRedacted,
}

impl EventMeta {
    fn get_event_type(&self) -> Option<&LitStr> {
        if let Self::Type(lit) = self {
            Some(lit)
        } else {
            None
        }
    }
}

impl Parse for EventMeta {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        if input.parse::<Token![type]>().is_ok() {
            input.parse::<Token![=]>()?;
            Ok(EventMeta::Type(input.parse::<LitStr>()?))
        } else if input.parse::<kw::skip_redaction>().is_ok() {
            Ok(EventMeta::SkipRedacted)
        } else if input.parse::<kw::custom_redacted>().is_ok() {
            Ok(EventMeta::CustomRedacted)
        } else {
            Err(syn::Error::new(input.span(), "not a recognized `ruma_event` attribute"))
        }
    }
}

struct MetaAttrs(Vec<EventMeta>);

impl MetaAttrs {
    fn is_custom(&self) -> bool {
        self.0.iter().any(|a| matches!(a, &EventMeta::CustomRedacted))
    }

    fn get_event_type(&self) -> Option<&LitStr> {
        self.0.iter().find_map(|a| a.get_event_type())
    }
}

impl Parse for MetaAttrs {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let attrs = syn::punctuated::Punctuated::<EventMeta, Token![,]>::parse_terminated(input)?;
        Ok(Self(attrs.into_iter().collect()))
    }
}

/// Create an `EventContent` implementation for a struct.
pub fn expand_event_content(
    input: &DeriveInput,
    emit_redacted: bool,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers };
    let serde = quote! { #ruma_events::exports::serde };
    let serde_json = quote! { #ruma_events::exports::serde_json };

    let ident = &input.ident;

    let content_attr = input
        .attrs
        .iter()
        .filter(|attr| attr.path.is_ident("ruma_event"))
        .map(|attr| attr.parse_args::<MetaAttrs>())
        .collect::<syn::Result<Vec<_>>>()?;

    let event_type = content_attr.iter().find_map(|a| a.get_event_type()).ok_or_else(|| {
        let msg = "no event type attribute found, \
            add `#[ruma_event(type = \"any.room.event\")]` \
            below the event content derive";

        syn::Error::new(Span::call_site(), msg)
    })?;

    let redacted = if emit_redacted && needs_redacted(&content_attr) {
        let doc = format!("The payload for a redacted `{}`", ident);
        let redacted_ident = format_ident!("Redacted{}", ident);
        let kept_redacted_fields = if let syn::Data::Struct(syn::DataStruct {
            fields: syn::Fields::Named(syn::FieldsNamed { named, .. }),
            ..
        }) = &input.data
        {
            // this is to validate the `#[ruma_event(skip_redaction)]` attribute
            named
                .iter()
                .flat_map(|f| &f.attrs)
                .filter(|a| a.path.is_ident("ruma_event"))
                .find_map(|a| {
                    if let Err(e) = a.parse_args::<EventMeta>() {
                        Some(Err(e))
                    } else {
                        None
                    }
                })
                .unwrap_or(Ok(()))?;

            let mut fields = named
                .iter()
                .filter(|f| {
                    matches!(
                        f.attrs.iter().find_map(|a| a.parse_args::<EventMeta>().ok()),
                        Some(EventMeta::SkipRedacted)
                    )
                })
                .cloned()
                .collect::<Vec<_>>();

            // don't re-emit our `ruma_event` attributes
            for f in &mut fields {
                f.attrs.retain(|a| !a.path.is_ident("ruma_event"));
            }
            fields
        } else {
            vec![]
        };
        let redaction_struct_fields = kept_redacted_fields.iter().flat_map(|f| &f.ident);

        // redacted_fields allows one to declare an empty redacted event without braces,
        // otherwise `RedactedWhateverEventContent {}` is needed.
        // The redacted_return is used in `EventContent::redacted` which only returns
        // zero sized types (unit structs).
        let (redacted_fields, redacted_return) = if kept_redacted_fields.is_empty() {
            (quote! { ; }, quote! { Ok(#redacted_ident {}) })
        } else {
            (
                quote! {
                    { #( #kept_redacted_fields, )* }
                },
                quote! {
                    Err(#serde::de::Error::custom(
                        format!("this redacted event has fields that cannot be constructed")
                    ))
                },
            )
        };

        let has_deserialize_fields = if kept_redacted_fields.is_empty() {
            quote! { #ruma_events::HasDeserializeFields::False }
        } else {
            quote! { #ruma_events::HasDeserializeFields::True }
        };

        let has_serialize_fields = if kept_redacted_fields.is_empty() {
            quote! { false }
        } else {
            quote! { true }
        };

        let redacted_event_content =
            generate_event_content_impl(&redacted_ident, event_type, ruma_events);

        quote! {
            // this is the non redacted event content's impl
            #[automatically_derived]
            impl #ident {
                /// Transforms the full event content into a redacted content according to spec.
                pub fn redact(self, version: #ruma_identifiers::RoomVersionId) -> #redacted_ident {
                    #redacted_ident {
                        #( #redaction_struct_fields: self.#redaction_struct_fields, )*
                    }
                }
            }

            #[doc = #doc]
            #[derive(Clone, Debug, #serde::Deserialize, #serde::Serialize)]
            pub struct #redacted_ident #redacted_fields

            #redacted_event_content

            #[automatically_derived]
            impl #ruma_events::RedactedEventContent for #redacted_ident {
                fn empty(ev_type: &str) -> Result<Self, #serde_json::Error> {
                    if ev_type != #event_type {
                        return Err(#serde::de::Error::custom(
                            format!("expected event type `{}`, found `{}`", #event_type, ev_type)
                        ));
                    }

                    #redacted_return
                }

                fn has_serialize_fields(&self) -> bool {
                    #has_serialize_fields
                }

                fn has_deserialize_fields() -> #ruma_events::HasDeserializeFields {
                    #has_deserialize_fields
                }
            }
        }
    } else {
        TokenStream::new()
    };

    let event_content = generate_event_content_impl(ident, event_type, ruma_events);

    Ok(quote! {
        #event_content

        #redacted
    })
}

/// Create a `BasicEventContent` implementation for a struct
pub fn expand_basic_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let event_content_impl = expand_event_content(input, false, ruma_events)?;

    Ok(quote! {
        #event_content_impl

        #[automatically_derived]
        impl #ruma_events::BasicEventContent for #ident {}
    })
}

/// Create a `EphemeralRoomEventContent` implementation for a struct
pub fn expand_ephemeral_room_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let event_content_impl = expand_event_content(input, false, ruma_events)?;

    Ok(quote! {
        #event_content_impl

        #[automatically_derived]
        impl #ruma_events::EphemeralRoomEventContent for #ident {}
    })
}

/// Create a `RoomEventContent` implementation for a struct.
pub fn expand_room_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let event_content_impl = expand_event_content(input, true, ruma_events)?;

    Ok(quote! {
        #event_content_impl

        #[automatically_derived]
        impl #ruma_events::RoomEventContent for #ident {}
    })
}

/// Create a `MessageEventContent` implementation for a struct
pub fn expand_message_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let room_ev_content = expand_room_event_content(input, ruma_events)?;

    let redacted_marker_trait = if needs_redacted_from_input(input) {
        let ident = format_ident!("Redacted{}", &ident);
        quote! {
            #[automatically_derived]
            impl #ruma_events::RedactedMessageEventContent for #ident {}
        }
    } else {
        TokenStream::new()
    };

    Ok(quote! {
        #room_ev_content

        #[automatically_derived]
        impl #ruma_events::MessageEventContent for #ident {}

        #redacted_marker_trait
    })
}

/// Create a `StateEventContent` implementation for a struct
pub fn expand_state_event_content(
    input: &DeriveInput,
    ruma_events: &TokenStream,
) -> syn::Result<TokenStream> {
    let ident = input.ident.clone();
    let room_ev_content = expand_room_event_content(input, ruma_events)?;

    let redacted_marker_trait = if needs_redacted_from_input(input) {
        let ident = format_ident!("Redacted{}", input.ident);
        quote! {
            #[automatically_derived]
            impl #ruma_events::RedactedStateEventContent for #ident {}
        }
    } else {
        TokenStream::new()
    };

    Ok(quote! {
        #room_ev_content

        #[automatically_derived]
        impl #ruma_events::StateEventContent for #ident {}

        #redacted_marker_trait
    })
}

fn generate_event_content_impl(
    ident: &Ident,
    event_type: &LitStr,
    ruma_events: &TokenStream,
) -> TokenStream {
    let serde = quote! { #ruma_events::exports::serde };
    let serde_json = quote! { #ruma_events::exports::serde_json };

    quote! {
        #[automatically_derived]
        impl #ruma_events::EventContent for #ident {
            fn event_type(&self) -> &str {
                #event_type
            }

            fn from_parts(
                ev_type: &str,
                content: Box<#serde_json::value::RawValue>
            ) -> Result<Self, #serde_json::Error> {
                if ev_type != #event_type {
                    return Err(#serde::de::Error::custom(
                        format!("expected event type `{}`, found `{}`", #event_type, ev_type)
                    ));
                }

                #serde_json::from_str(content.get())
            }
        }
    }
}

fn needs_redacted(input: &[MetaAttrs]) -> bool {
    // `is_custom` means that the content struct does not need a generated
    // redacted struct also. If no `custom_redacted` attrs are found the content
    // needs a redacted struct generated.
    !input.iter().any(|a| a.is_custom())
}

fn needs_redacted_from_input(input: &DeriveInput) -> bool {
    !input.attrs.iter().flat_map(|a| a.parse_args::<MetaAttrs>().ok()).any(|a| a.is_custom())
}
<|endoftext|>


<commit_before>//! Helper functions to ease dealing with surface trees

use crate::{
    backend::renderer::{
        element::{PrimaryScanoutOutput, RenderElementState, RenderElementStates},
        utils::RendererSurfaceState,
    },
    desktop::WindowSurfaceType,
    output::Output,
    utils::{Logical, Point, Rectangle},
    wayland::compositor::{with_surface_tree_downward, SurfaceAttributes, SurfaceData, TraversalAction},
};
use std::{cell::RefCell, sync::Mutex, time::Duration};
use wayland_server::protocol::wl_surface;

impl RendererSurfaceState {
    fn contains_point<P: Into<Point<f64, Logical>>>(&self, attrs: &SurfaceAttributes, point: P) -> bool {
        let point = point.into();
        let size = match self.surface_view.map(|view| view.dst) {
            None => return false, // If the surface has no size, it can't have an input region.
            Some(size) => size,
        };

        let rect = Rectangle {
            loc: (0, 0).into(),
            size,
        }
        .to_f64();

        // The input region is always within the surface itself, so if the surface itself doesn't contain the
        // point we can return false.
        if !rect.contains(point) {
            return false;
        }

        // If there's no input region, we're done.
        if attrs.input_region.is_none() {
            return true;
        }

        attrs
            .input_region
            .as_ref()
            .unwrap()
            .contains(point.to_i32_round())
    }
}

/// Returns the bounding box of a given surface and all its subsurfaces.
///
/// - `location` can be set to offset the returned bounding box.
pub fn bbox_from_surface_tree<P>(surface: &wl_surface::WlSurface, location: P) -> Rectangle<i32, Logical>
where
    P: Into<Point<i32, Logical>>,
{
    let location = location.into();
    let mut bounding_box = Rectangle::from_loc_and_size(location, (0, 0));
    with_surface_tree_downward(
        surface,
        location,
        |_, states, loc: &Point<i32, Logical>| {
            let mut loc = *loc;
            let data = states.data_map.get::<RefCell<RendererSurfaceState>>();

            if let Some(surface_view) = data.and_then(|d| d.borrow().surface_view) {
                loc += surface_view.offset;
                // Update the bounding box.
                bounding_box = bounding_box.merge(Rectangle::from_loc_and_size(loc, surface_view.dst));

                TraversalAction::DoChildren(loc)
            } else {
                // If the parent surface is unmapped, then the child surfaces are hidden as
                // well, no need to consider them here.
                TraversalAction::SkipChildren
            }
        },
        |_, _, _| {},
        |_, _, _| true,
    );
    bounding_box
}

/// Returns the topmost (sub-)surface under a given position matching the input regions of the surface.
///
/// In case no surface input region matches the point [`None`] is returned.
///
/// - `point` has to be the position to query, relative to (0, 0) of the given surface + `location`.
/// - `location` can be used to offset the returned point.
pub fn under_from_surface_tree<P>(
    surface: &wl_surface::WlSurface,
    point: Point<f64, Logical>,
    location: P,
    surface_type: WindowSurfaceType,
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)>
where
    P: Into<Point<i32, Logical>>,
{
    let found = RefCell::new(None);
    with_surface_tree_downward(
        surface,
        location.into(),
        |wl_surface, states, location: &Point<i32, Logical>| {
            let mut location = *location;
            let data = states.data_map.get::<RefCell<RendererSurfaceState>>();

            if let Some(surface_view) = data.and_then(|d| d.borrow().surface_view) {
                location += surface_view.offset;

                if states.role == Some("subsurface") || surface_type.contains(WindowSurfaceType::TOPLEVEL) {
                    let contains_the_point = data
                        .map(|data| {
                            data.borrow()
                                .contains_point(&*states.cached_state.current(), point - location.to_f64())
                        })
                        .unwrap_or(false);
                    if contains_the_point {
                        *found.borrow_mut() = Some((wl_surface.clone(), location));
                    }
                }

                if surface_type.contains(WindowSurfaceType::SUBSURFACE) {
                    TraversalAction::DoChildren(location)
                } else {
                    TraversalAction::SkipChildren
                }
            } else {
                // We are completely hidden
                TraversalAction::SkipChildren
            }
        },
        |_, _, _| {},
        |_, _, _| {
            // only continue if the point is not found
            found.borrow().is_none()
        },
    );
    found.into_inner()
}

type SurfacePrimaryScanoutOutput = Mutex<PrimaryScanoutOutput>;

/// Run a closure on all surfaces of a surface tree
pub fn with_surfaces_surface_tree<F>(surface: &wl_surface::WlSurface, mut processor: F)
where
    F: FnMut(&wl_surface::WlSurface, &SurfaceData),
{
    with_surface_tree_downward(
        surface,
        (),
        |_, _, _| TraversalAction::DoChildren(()),
        |surface, states, _| processor(surface, states),
        |_, _, _| true,
    )
}

/// Retrieve a previously stored primary scan-out output from a surface
///
/// This will always return `None` if [`update_surface_primary_scanout_output`] is not used.
pub fn surface_primary_scanout_output(
    _surface: &wl_surface::WlSurface,
    states: &SurfaceData,
) -> Option<Output> {
    states
        .data_map
        .insert_if_missing_threadsafe(SurfacePrimaryScanoutOutput::default);
    let surface_primary_scanout_output = states.data_map.get::<SurfacePrimaryScanoutOutput>().unwrap();
    surface_primary_scanout_output.lock().unwrap().current_output()
}

/// Update the surface primary scan-out output from a output render report
///
/// The compare function can be used to alter the behavior for selecting the primary scan-out
/// output. See [`update_from_render_element_states`](crate::backend::renderer::element::PrimaryScanoutOutput::update_from_render_element_states) for more information about primary scan-out
/// output selection.
pub fn update_surface_primary_scanout_output<F>(
    surface: &wl_surface::WlSurface,
    output: &Output,
    surface_data: &SurfaceData,
    states: &RenderElementStates,
    compare: F,
) where
    F: for<'a> Fn(&'a Output, &'a RenderElementState, &'a Output, &'a RenderElementState) -> &'a Output,
{
    surface_data
        .data_map
        .insert_if_missing_threadsafe(SurfacePrimaryScanoutOutput::default);
    let surface_primary_scanout_output = surface_data
        .data_map
        .get::<SurfacePrimaryScanoutOutput>()
        .unwrap();
    surface_primary_scanout_output
        .lock()
        .unwrap()
        .update_from_render_element_states(surface, output, states, compare);
}

/// Sends frame callbacks for a surface and its subsurfaces with the given `time`.
///
/// The frame callbacks for a [`WlSurface`](wl_surface::WlSurface) will only be sent if the
/// primary scan-out output equals the provided output or if the surface has no primary
/// scan-out output and the frame callback is overdue. A frame callback is considered
/// overdue if the last time a frame callback has been sent is greater than the provided
/// throttle threshold. If the threshold is `None` this will never send frame callbacks
/// for a surface that is not visible. Specifying [`Duration::ZERO`] as the throttle threshold
/// will always send frame callbacks for non visible surfaces.
#[allow(clippy::too_many_arguments)]
pub fn send_frames_surface_tree<T, F>(
    surface: &wl_surface::WlSurface,
    output: &Output,
    time: T,
    throttle: Option<Duration>,
    mut primary_scan_out_output: F,
) where
    T: Into<Duration>,
    F: FnMut(&wl_surface::WlSurface, &SurfaceData) -> Option<Output>,
{
    let time = time.into();

    with_surface_tree_downward(
        surface,
        (),
        |_, _, &()| TraversalAction::DoChildren(()),
        |surface, states, &()| {
            states
                .data_map
                .insert_if_missing_threadsafe(SurfaceFrameThrottlingState::default);
            let surface_frame_throttling_state =
                states.data_map.get::<SurfaceFrameThrottlingState>().unwrap();

            let on_primary_scanout_output = primary_scan_out_output(surface, states)
                .map(|preferred_output| preferred_output == *output)
                .unwrap_or(false);

            let frame_overdue = surface_frame_throttling_state.update(time, throttle);

            // We only want to send frame callbacks on the primary scan-out output
            // or if we have no output and the frame is overdue, this can only
            // happen if the surface is completely occluded on all outputs
            let send_frame_callback = on_primary_scanout_output || frame_overdue;

            if send_frame_callback {
                // the surface may not have any user_data if it is a subsurface and has not
                // yet been commited
                for callback in states
                    .cached_state
                    .current::<SurfaceAttributes>()
                    .frame_callbacks
                    .drain(..)
                {
                    callback.done(time.as_millis() as u32);
                }
            }
        },
        |_, _, &()| true,
    );
}

#[derive(Debug, Default)]
struct SurfaceFrameThrottlingState(Mutex<Option<Duration>>);

impl SurfaceFrameThrottlingState {
    pub fn update(&self, time: Duration, throttle: Option<Duration>) -> bool {
        if let Some(throttle) = throttle {
            let mut guard = self.0.lock().unwrap();
            let send_throttled_frame = guard
                .map(|last| time.saturating_sub(last) > throttle)
                .unwrap_or(true);
            if send_throttled_frame {
                *guard = Some(time);
            }
            send_throttled_frame
        } else {
            false
        }
    }
}
<commit_msg>desktop: remove unnecessary clippy allow<commit_after>//! Helper functions to ease dealing with surface trees

use crate::{
    backend::renderer::{
        element::{PrimaryScanoutOutput, RenderElementState, RenderElementStates},
        utils::RendererSurfaceState,
    },
    desktop::WindowSurfaceType,
    output::Output,
    utils::{Logical, Point, Rectangle},
    wayland::compositor::{with_surface_tree_downward, SurfaceAttributes, SurfaceData, TraversalAction},
};
use std::{cell::RefCell, sync::Mutex, time::Duration};
use wayland_server::protocol::wl_surface;

impl RendererSurfaceState {
    fn contains_point<P: Into<Point<f64, Logical>>>(&self, attrs: &SurfaceAttributes, point: P) -> bool {
        let point = point.into();
        let size = match self.surface_view.map(|view| view.dst) {
            None => return false, // If the surface has no size, it can't have an input region.
            Some(size) => size,
        };

        let rect = Rectangle {
            loc: (0, 0).into(),
            size,
        }
        .to_f64();

        // The input region is always within the surface itself, so if the surface itself doesn't contain the
        // point we can return false.
        if !rect.contains(point) {
            return false;
        }

        // If there's no input region, we're done.
        if attrs.input_region.is_none() {
            return true;
        }

        attrs
            .input_region
            .as_ref()
            .unwrap()
            .contains(point.to_i32_round())
    }
}

/// Returns the bounding box of a given surface and all its subsurfaces.
///
/// - `location` can be set to offset the returned bounding box.
pub fn bbox_from_surface_tree<P>(surface: &wl_surface::WlSurface, location: P) -> Rectangle<i32, Logical>
where
    P: Into<Point<i32, Logical>>,
{
    let location = location.into();
    let mut bounding_box = Rectangle::from_loc_and_size(location, (0, 0));
    with_surface_tree_downward(
        surface,
        location,
        |_, states, loc: &Point<i32, Logical>| {
            let mut loc = *loc;
            let data = states.data_map.get::<RefCell<RendererSurfaceState>>();

            if let Some(surface_view) = data.and_then(|d| d.borrow().surface_view) {
                loc += surface_view.offset;
                // Update the bounding box.
                bounding_box = bounding_box.merge(Rectangle::from_loc_and_size(loc, surface_view.dst));

                TraversalAction::DoChildren(loc)
            } else {
                // If the parent surface is unmapped, then the child surfaces are hidden as
                // well, no need to consider them here.
                TraversalAction::SkipChildren
            }
        },
        |_, _, _| {},
        |_, _, _| true,
    );
    bounding_box
}

/// Returns the topmost (sub-)surface under a given position matching the input regions of the surface.
///
/// In case no surface input region matches the point [`None`] is returned.
///
/// - `point` has to be the position to query, relative to (0, 0) of the given surface + `location`.
/// - `location` can be used to offset the returned point.
pub fn under_from_surface_tree<P>(
    surface: &wl_surface::WlSurface,
    point: Point<f64, Logical>,
    location: P,
    surface_type: WindowSurfaceType,
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)>
where
    P: Into<Point<i32, Logical>>,
{
    let found = RefCell::new(None);
    with_surface_tree_downward(
        surface,
        location.into(),
        |wl_surface, states, location: &Point<i32, Logical>| {
            let mut location = *location;
            let data = states.data_map.get::<RefCell<RendererSurfaceState>>();

            if let Some(surface_view) = data.and_then(|d| d.borrow().surface_view) {
                location += surface_view.offset;

                if states.role == Some("subsurface") || surface_type.contains(WindowSurfaceType::TOPLEVEL) {
                    let contains_the_point = data
                        .map(|data| {
                            data.borrow()
                                .contains_point(&*states.cached_state.current(), point - location.to_f64())
                        })
                        .unwrap_or(false);
                    if contains_the_point {
                        *found.borrow_mut() = Some((wl_surface.clone(), location));
                    }
                }

                if surface_type.contains(WindowSurfaceType::SUBSURFACE) {
                    TraversalAction::DoChildren(location)
                } else {
                    TraversalAction::SkipChildren
                }
            } else {
                // We are completely hidden
                TraversalAction::SkipChildren
            }
        },
        |_, _, _| {},
        |_, _, _| {
            // only continue if the point is not found
            found.borrow().is_none()
        },
    );
    found.into_inner()
}

type SurfacePrimaryScanoutOutput = Mutex<PrimaryScanoutOutput>;

/// Run a closure on all surfaces of a surface tree
pub fn with_surfaces_surface_tree<F>(surface: &wl_surface::WlSurface, mut processor: F)
where
    F: FnMut(&wl_surface::WlSurface, &SurfaceData),
{
    with_surface_tree_downward(
        surface,
        (),
        |_, _, _| TraversalAction::DoChildren(()),
        |surface, states, _| processor(surface, states),
        |_, _, _| true,
    )
}

/// Retrieve a previously stored primary scan-out output from a surface
///
/// This will always return `None` if [`update_surface_primary_scanout_output`] is not used.
pub fn surface_primary_scanout_output(
    _surface: &wl_surface::WlSurface,
    states: &SurfaceData,
) -> Option<Output> {
    states
        .data_map
        .insert_if_missing_threadsafe(SurfacePrimaryScanoutOutput::default);
    let surface_primary_scanout_output = states.data_map.get::<SurfacePrimaryScanoutOutput>().unwrap();
    surface_primary_scanout_output.lock().unwrap().current_output()
}

/// Update the surface primary scan-out output from a output render report
///
/// The compare function can be used to alter the behavior for selecting the primary scan-out
/// output. See [`update_from_render_element_states`](crate::backend::renderer::element::PrimaryScanoutOutput::update_from_render_element_states) for more information about primary scan-out
/// output selection.
pub fn update_surface_primary_scanout_output<F>(
    surface: &wl_surface::WlSurface,
    output: &Output,
    surface_data: &SurfaceData,
    states: &RenderElementStates,
    compare: F,
) where
    F: for<'a> Fn(&'a Output, &'a RenderElementState, &'a Output, &'a RenderElementState) -> &'a Output,
{
    surface_data
        .data_map
        .insert_if_missing_threadsafe(SurfacePrimaryScanoutOutput::default);
    let surface_primary_scanout_output = surface_data
        .data_map
        .get::<SurfacePrimaryScanoutOutput>()
        .unwrap();
    surface_primary_scanout_output
        .lock()
        .unwrap()
        .update_from_render_element_states(surface, output, states, compare);
}

/// Sends frame callbacks for a surface and its subsurfaces with the given `time`.
///
/// The frame callbacks for a [`WlSurface`](wl_surface::WlSurface) will only be sent if the
/// primary scan-out output equals the provided output or if the surface has no primary
/// scan-out output and the frame callback is overdue. A frame callback is considered
/// overdue if the last time a frame callback has been sent is greater than the provided
/// throttle threshold. If the threshold is `None` this will never send frame callbacks
/// for a surface that is not visible. Specifying [`Duration::ZERO`] as the throttle threshold
/// will always send frame callbacks for non visible surfaces.
pub fn send_frames_surface_tree<T, F>(
    surface: &wl_surface::WlSurface,
    output: &Output,
    time: T,
    throttle: Option<Duration>,
    mut primary_scan_out_output: F,
) where
    T: Into<Duration>,
    F: FnMut(&wl_surface::WlSurface, &SurfaceData) -> Option<Output>,
{
    let time = time.into();

    with_surface_tree_downward(
        surface,
        (),
        |_, _, &()| TraversalAction::DoChildren(()),
        |surface, states, &()| {
            states
                .data_map
                .insert_if_missing_threadsafe(SurfaceFrameThrottlingState::default);
            let surface_frame_throttling_state =
                states.data_map.get::<SurfaceFrameThrottlingState>().unwrap();

            let on_primary_scanout_output = primary_scan_out_output(surface, states)
                .map(|preferred_output| preferred_output == *output)
                .unwrap_or(false);

            let frame_overdue = surface_frame_throttling_state.update(time, throttle);

            // We only want to send frame callbacks on the primary scan-out output
            // or if we have no output and the frame is overdue, this can only
            // happen if the surface is completely occluded on all outputs
            let send_frame_callback = on_primary_scanout_output || frame_overdue;

            if send_frame_callback {
                // the surface may not have any user_data if it is a subsurface and has not
                // yet been commited
                for callback in states
                    .cached_state
                    .current::<SurfaceAttributes>()
                    .frame_callbacks
                    .drain(..)
                {
                    callback.done(time.as_millis() as u32);
                }
            }
        },
        |_, _, &()| true,
    );
}

#[derive(Debug, Default)]
struct SurfaceFrameThrottlingState(Mutex<Option<Duration>>);

impl SurfaceFrameThrottlingState {
    pub fn update(&self, time: Duration, throttle: Option<Duration>) -> bool {
        if let Some(throttle) = throttle {
            let mut guard = self.0.lock().unwrap();
            let send_throttled_frame = guard
                .map(|last| time.saturating_sub(last) > throttle)
                .unwrap_or(true);
            if send_throttled_frame {
                *guard = Some(time);
            }
            send_throttled_frame
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of the `Standard` distribution for integer types.

use {Rng};
use distributions::{Distribution, Standard};

impl Distribution<u8> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Distribution<u16> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Distribution<u32> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Distribution<u64> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Distribution<u128> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
        // Use LE; we explicitly generate one value before the next.
        let x = rng.next_u64() as u128;
        let y = rng.next_u64() as u128;
        (y << 64) | x
    }
}

impl Distribution<usize> for Standard {
    #[inline]
    #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u32() as usize
    }

    #[inline]
    #[cfg(target_pointer_width = "64")]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u64() as usize
    }
}

macro_rules! impl_int_from_uint {
    ($ty:ty, $uty:ty) => {
        impl Distribution<$ty> for Standard {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
                rng.gen::<$uty>() as $ty
            }
        }
    }
}

impl_int_from_uint! { i8, u8 }
impl_int_from_uint! { i16, u16 }
impl_int_from_uint! { i32, u32 }
impl_int_from_uint! { i64, u64 }
#[cfg(feature = "i128_support")] impl_int_from_uint! { i128, u128 }
impl_int_from_uint! { isize, usize }

#[cfg(test)]
mod tests {
    use Rng;
    use distributions::{Standard};

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng(806);

        rng.sample::<isize, _>(Standard);
        rng.sample::<i8, _>(Standard);
        rng.sample::<i16, _>(Standard);
        rng.sample::<i32, _>(Standard);
        rng.sample::<i64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<i128, _>(Standard);

        rng.sample::<usize, _>(Standard);
        rng.sample::<u8, _>(Standard);
        rng.sample::<u16, _>(Standard);
        rng.sample::<u32, _>(Standard);
        rng.sample::<u64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<u128, _>(Standard);
    }
}
<commit_msg>Implement Standard for SIMD integer types<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of the `Standard` distribution for integer types.

use {Rng};
use distributions::{Distribution, Standard};
#[cfg(feature="simd_support")]
use core::simd::*;

impl Distribution<u8> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Distribution<u16> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Distribution<u32> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Distribution<u64> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Distribution<u128> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
        // Use LE; we explicitly generate one value before the next.
        let x = rng.next_u64() as u128;
        let y = rng.next_u64() as u128;
        (y << 64) | x
    }
}

impl Distribution<usize> for Standard {
    #[inline]
    #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u32() as usize
    }

    #[inline]
    #[cfg(target_pointer_width = "64")]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u64() as usize
    }
}

macro_rules! impl_int_from_uint {
    ($ty:ty, $uty:ty) => {
        impl Distribution<$ty> for Standard {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
                rng.gen::<$uty>() as $ty
            }
        }
    }
}

impl_int_from_uint! { i8, u8 }
impl_int_from_uint! { i16, u16 }
impl_int_from_uint! { i32, u32 }
impl_int_from_uint! { i64, u64 }
#[cfg(feature = "i128_support")] impl_int_from_uint! { i128, u128 }
impl_int_from_uint! { isize, usize }

#[cfg(feature="simd_support")]
macro_rules! simd_impl {
    ($bits:expr,) => {};
    ($bits:expr, $ty:ty, $($ty_more:ty,)*) => {
        simd_impl!($bits, $($ty_more,)*);

        impl Distribution<$ty> for Standard {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
                let mut vec = Default::default();
                unsafe {
                    let ptr = &mut vec;
                    let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]);
                    rng.fill_bytes(b_ptr);
                }
                vec
            }
        }
    }
}

#[cfg(feature="simd_support")]
simd_impl!(16, u8x2, i8x2,);
#[cfg(feature="simd_support")]
simd_impl!(32, u8x4, i8x4, u16x2, i16x2,);
#[cfg(feature="simd_support")]
simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,);
#[cfg(feature="simd_support")]
simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,);
#[cfg(feature="simd_support")]
simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,);
#[cfg(feature="simd_support")]
simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,);

#[cfg(test)]
mod tests {
    use Rng;
    use distributions::{Standard};

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng(806);

        rng.sample::<isize, _>(Standard);
        rng.sample::<i8, _>(Standard);
        rng.sample::<i16, _>(Standard);
        rng.sample::<i32, _>(Standard);
        rng.sample::<i64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<i128, _>(Standard);

        rng.sample::<usize, _>(Standard);
        rng.sample::<u8, _>(Standard);
        rng.sample::<u16, _>(Standard);
        rng.sample::<u32, _>(Standard);
        rng.sample::<u64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<u128, _>(Standard);
    }
}
<|endoftext|>


<commit_before><commit_msg>Rustfmt atom.rs<commit_after><|endoftext|>


<commit_before><commit_msg>Set offsets with the builder pattern<commit_after><|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    backup_types::{
        epoch_ending::backup::{EpochEndingBackupController, EpochEndingBackupOpt},
        state_snapshot::backup::{StateSnapshotBackupController, StateSnapshotBackupOpt},
        transaction::backup::{TransactionBackupController, TransactionBackupOpt},
    },
    metadata,
    metadata::cache::MetadataCacheOpt,
    storage::BackupStorage,
    utils::{backup_service_client::BackupServiceClient, GlobalBackupOpt},
};
use anyhow::{anyhow, ensure, Result};
use futures::{stream, Future, StreamExt};
use libra_logger::prelude::*;
use libra_types::transaction::Version;
use libradb::backup::backup_handler::DbState;
use std::{fmt::Debug, sync::Arc};
use structopt::StructOpt;
use tokio::{
    sync::watch,
    time::{interval, Duration},
};

#[derive(StructOpt)]
pub struct BackupCoordinatorOpt {
    #[structopt(flatten)]
    pub metadata_cache_opt: MetadataCacheOpt,
    // We replay transactions on top of a state snapshot at about 2000 tps, having a state snapshot
    // every 2000 * 3600 * 2 = 14.4 Mil versions will guarantee that to achieve any state in
    // history, it won't take us more than two hours in transaction replaying. Defaulting to 10 Mil
    // here to make it less than two, and easier for eyes.
    #[structopt(long, default_value = "10000000")]
    pub state_snapshot_interval: usize,
    // Assuming the network runs at 100 tps, it's 100 * 3600 = 360k transactions per hour, we don't
    // want the backups to lag behind too much. Defaulting to 100k here in case the network is way
    // slower than expected.
    #[structopt(long, default_value = "100000")]
    pub transaction_batch_size: usize,
}

impl BackupCoordinatorOpt {
    fn validate(&self) -> Result<()> {
        ensure!(
            self.state_snapshot_interval > 0 && self.transaction_batch_size > 0,
            "Backup interval and batch size must be greater than 0."
        );
        Ok(())
    }
}

pub struct BackupCoordinator {
    client: Arc<BackupServiceClient>,
    storage: Arc<dyn BackupStorage>,
    global_opt: GlobalBackupOpt,
    metadata_cache_opt: MetadataCacheOpt,
    state_snapshot_interval: usize,
    transaction_batch_size: usize,
}

impl BackupCoordinator {
    pub fn new(
        opt: BackupCoordinatorOpt,
        global_opt: GlobalBackupOpt,
        client: Arc<BackupServiceClient>,
        storage: Arc<dyn BackupStorage>,
    ) -> Self {
        opt.validate().unwrap();
        Self {
            client,
            storage,
            global_opt,
            metadata_cache_opt: opt.metadata_cache_opt,
            state_snapshot_interval: opt.state_snapshot_interval,
            transaction_batch_size: opt.transaction_batch_size,
        }
    }
    pub async fn run(&self) -> Result<()> {
        // Connect to both the local Libra node and the backup storage.
        let backup_state =
            metadata::cache::sync_and_load(&self.metadata_cache_opt, Arc::clone(&self.storage))
                .await?
                .get_storage_state();
        let db_state = self
            .client
            .get_db_state()
            .await?
            .ok_or_else(|| anyhow!("DB not bootstrapped."))?;

        // On new DbState retrieved:
        // `watch_db_state` informs `backup_epoch_endings` via channel 1,
        // and the the latter informs the other backup type workers via channel 2, after epoch
        // ending is properly backed up, if necessary. This way, the epoch ending LedgerInfo needed
        // for proof verification is always available in the same backup storage.
        let (tx1, rx1) = watch::channel(db_state);
        let (tx2, rx2) = watch::channel(db_state);

        // Schedule work streams.
        let watch_db_state = interval(Duration::from_secs(1))
            .then(|_| self.try_refresh_db_state(&tx1))
            .boxed_local();

        let backup_epoch_endings = self
            .backup_work_stream(
                backup_state.latest_epoch_ending_epoch,
                &rx1,
                |slf, last_epoch, db_state| {
                    Self::backup_epoch_endings(slf, last_epoch, db_state, &tx2)
                },
            )
            .boxed_local();
        let backup_state_snapshots = self
            .backup_work_stream(
                backup_state.latest_state_snapshot_version,
                &rx2,
                Self::backup_state_snapshot,
            )
            .boxed_local();
        let backup_transactions = self
            .backup_work_stream(
                backup_state.latest_transaction_version,
                &rx2,
                Self::backup_transactions,
            )
            .boxed_local();

        info!("Backup coordinator started.");
        let mut all_work = stream::select_all(vec![
            watch_db_state,
            backup_epoch_endings,
            backup_state_snapshots,
            backup_transactions,
        ]);

        loop {
            all_work
                .next()
                .await
                .ok_or_else(|| anyhow!("Must be a bug: we never returned None."))?
        }
    }
}

impl BackupCoordinator {
    async fn try_refresh_db_state(&self, db_state_broadcast: &watch::Sender<DbState>) {
        match self.client.get_db_state().await {
            Ok(s) => db_state_broadcast
                .broadcast(s.expect("Db should have been bootstrapped."))
                .map_err(|e| anyhow!("Receivers should not be cancelled: {}", e))
                .unwrap(),
            Err(e) => warn!(
                "Failed pulling DbState from local Libra node: {}. Will keep trying.",
                e
            ),
        };
    }

    async fn backup_epoch_endings(
        &self,
        mut last_epoch_ending_epoch_in_backup: Option<u64>,
        db_state: DbState,
        downstream_db_state_broadcaster: &watch::Sender<DbState>,
    ) -> Result<Option<u64>> {
        loop {
            let (first, last) = get_batch_range(last_epoch_ending_epoch_in_backup, 1);

            if db_state.epoch <= last {
                // "<=" because `db_state.epoch` hasn't ended yet, wait for the next db_state update
                break;
            }

            EpochEndingBackupController::new(
                EpochEndingBackupOpt {
                    start_epoch: first,
                    end_epoch: last + 1,
                },
                self.global_opt.clone(),
                Arc::clone(&self.client),
                Arc::clone(&self.storage),
            )
            .run()
            .await?;
            last_epoch_ending_epoch_in_backup = Some(last)
        }

        downstream_db_state_broadcaster
            .broadcast(db_state)
            .map_err(|e| anyhow!("Receivers should not be cancelled: {}", e))
            .unwrap();
        Ok(last_epoch_ending_epoch_in_backup)
    }

    async fn backup_state_snapshot(
        &self,
        last_snapshot_version_in_backup: Option<Version>,
        db_state: DbState,
    ) -> Result<Option<Version>> {
        let next_snapshot_version = get_next_snapshot(
            last_snapshot_version_in_backup,
            db_state,
            self.state_snapshot_interval,
        );

        if db_state.committed_version < next_snapshot_version {
            // wait for the next db_state update
            return Ok(last_snapshot_version_in_backup);
        }

        StateSnapshotBackupController::new(
            StateSnapshotBackupOpt {
                version: next_snapshot_version,
            },
            self.global_opt.clone(),
            Arc::clone(&self.client),
            Arc::clone(&self.storage),
        )
        .run()
        .await?;

        Ok(Some(next_snapshot_version))
    }

    async fn backup_transactions(
        &self,
        mut last_transaction_version_in_backup: Option<Version>,
        db_state: DbState,
    ) -> Result<Option<u64>> {
        loop {
            let (first, last) = get_batch_range(
                last_transaction_version_in_backup,
                self.transaction_batch_size,
            );

            if db_state.committed_version < last {
                // wait for the next db_state update
                return Ok(last_transaction_version_in_backup);
            }

            TransactionBackupController::new(
                TransactionBackupOpt {
                    start_version: first,
                    num_transactions: (last + 1 - first) as usize,
                },
                self.global_opt.clone(),
                Arc::clone(&self.client),
                Arc::clone(&self.storage),
            )
            .run()
            .await?;

            last_transaction_version_in_backup = Some(last);
        }
    }

    fn backup_work_stream<'a, S, W, Fut>(
        &'a self,
        initial_state: S,
        db_state_rx: &'a watch::Receiver<DbState>,
        worker: W,
    ) -> impl StreamExt<Item = ()> + 'a
    where
        S: Copy + Debug + 'a,
        W: Worker<'a, S, Fut> + Copy + 'a,
        Fut: Future<Output = Result<S>> + 'a,
    {
        stream::unfold(
            (initial_state, db_state_rx.clone()),
            move |(s, mut rx)| async move {
                let db_state = rx
                    .recv()
                    .await
                    .ok_or_else(|| anyhow!("The broadcaster has been dropped."))
                    .unwrap();
                let next_state = worker(self, s, db_state).await.unwrap_or_else(|e| {
                    warn!("backup failed: {}. Keep trying with state {:?}.", e, s);
                    s
                });
                Some(((), (next_state, rx)))
            },
        )
    }
}

trait Worker<'a, S, Fut: Future<Output = Result<S>> + 'a>:
    Fn(&'a BackupCoordinator, S, DbState) -> Fut
{
}

impl<'a, T, S, Fut> Worker<'a, S, Fut> for T
where
    T: Fn(&'a BackupCoordinator, S, DbState) -> Fut,
    Fut: Future<Output = Result<S>> + 'a,
{
}

fn get_batch_range(last_in_backup: Option<u64>, batch_size: usize) -> (u64, u64) {
    // say, 7 is already in backup, and we target batches of size 10, we will return (8, 10) in this
    // case, so 8, 9, 10 will be in this batch, and next time the backup worker will pass in 10,
    // and we will return (11, 20). The transaction 0 will be in it's own batch.
    last_in_backup.map_or((0, 0), |n| {
        let first = n + 1;
        let batch = n / batch_size as u64 + 1;
        let last = batch * batch_size as u64;
        (first, last)
    })
}

fn get_next_snapshot(last_in_backup: Option<u64>, db_state: DbState, interval: usize) -> u64 {
    // We don't try to guarantee snapshots are taken at each applicable interval: when the backup
    // progress can't keep up with the ledger growth, we favor timeliness over completeness.
    // For example, with interval 100, when we finished taking a snapshot at version 700, if we
    // found the latest version is already 1250, the next snapshot we take will be at 1200, not 800.

    let next_for_storage = match last_in_backup {
        Some(last) => (last / interval as u64 + 1) * interval as u64,
        None => 0,
    };

    let last_for_db: u64 = db_state.committed_version / interval as u64 * interval as u64;

    std::cmp::max(next_for_storage, last_for_db)
}

#[cfg(test)]
mod tests {
    use crate::coordinators::backup::{get_batch_range, get_next_snapshot};
    use libradb::backup::backup_handler::DbState;

    #[test]
    fn test_get_batch_range() {
        assert_eq!(get_batch_range(None, 100), (0, 0));
        assert_eq!(get_batch_range(Some(0), 100), (1, 100));
        assert_eq!(get_batch_range(Some(100), 50), (101, 150));
        assert_eq!(get_batch_range(Some(150), 100), (151, 200));
        assert_eq!(get_batch_range(Some(200), 100), (201, 300));
    }

    #[test]
    fn test_get_next_snapshot() {
        let _state = |v| DbState {
            epoch: 0,
            committed_version: v,
            synced_version: v,
        };

        assert_eq!(get_next_snapshot(None, _state(90), 100), 0);
        assert_eq!(get_next_snapshot(Some(0), _state(90), 100), 100);
        assert_eq!(get_next_snapshot(Some(0), _state(190), 100), 100);
        assert_eq!(get_next_snapshot(Some(0), _state(200), 100), 200);
        assert_eq!(get_next_snapshot(Some(0), _state(250), 100), 200);
        assert_eq!(get_next_snapshot(Some(200), _state(250), 100), 300);
    }
}
<commit_msg>[backup] backup coordinator: fix that "epoch first" not guranteed on start<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    backup_types::{
        epoch_ending::backup::{EpochEndingBackupController, EpochEndingBackupOpt},
        state_snapshot::backup::{StateSnapshotBackupController, StateSnapshotBackupOpt},
        transaction::backup::{TransactionBackupController, TransactionBackupOpt},
    },
    metadata,
    metadata::cache::MetadataCacheOpt,
    storage::BackupStorage,
    utils::{backup_service_client::BackupServiceClient, GlobalBackupOpt},
};
use anyhow::{anyhow, ensure, Result};
use futures::{stream, Future, StreamExt};
use libra_logger::prelude::*;
use libra_types::transaction::Version;
use libradb::backup::backup_handler::DbState;
use std::{fmt::Debug, sync::Arc};
use structopt::StructOpt;
use tokio::{
    sync::watch,
    time::{interval, Duration},
};

#[derive(StructOpt)]
pub struct BackupCoordinatorOpt {
    #[structopt(flatten)]
    pub metadata_cache_opt: MetadataCacheOpt,
    // We replay transactions on top of a state snapshot at about 2000 tps, having a state snapshot
    // every 2000 * 3600 * 2 = 14.4 Mil versions will guarantee that to achieve any state in
    // history, it won't take us more than two hours in transaction replaying. Defaulting to 10 Mil
    // here to make it less than two, and easier for eyes.
    #[structopt(long, default_value = "10000000")]
    pub state_snapshot_interval: usize,
    // Assuming the network runs at 100 tps, it's 100 * 3600 = 360k transactions per hour, we don't
    // want the backups to lag behind too much. Defaulting to 100k here in case the network is way
    // slower than expected.
    #[structopt(long, default_value = "100000")]
    pub transaction_batch_size: usize,
}

impl BackupCoordinatorOpt {
    fn validate(&self) -> Result<()> {
        ensure!(
            self.state_snapshot_interval > 0 && self.transaction_batch_size > 0,
            "Backup interval and batch size must be greater than 0."
        );
        Ok(())
    }
}

pub struct BackupCoordinator {
    client: Arc<BackupServiceClient>,
    storage: Arc<dyn BackupStorage>,
    global_opt: GlobalBackupOpt,
    metadata_cache_opt: MetadataCacheOpt,
    state_snapshot_interval: usize,
    transaction_batch_size: usize,
}

impl BackupCoordinator {
    pub fn new(
        opt: BackupCoordinatorOpt,
        global_opt: GlobalBackupOpt,
        client: Arc<BackupServiceClient>,
        storage: Arc<dyn BackupStorage>,
    ) -> Self {
        opt.validate().unwrap();
        Self {
            client,
            storage,
            global_opt,
            metadata_cache_opt: opt.metadata_cache_opt,
            state_snapshot_interval: opt.state_snapshot_interval,
            transaction_batch_size: opt.transaction_batch_size,
        }
    }
    pub async fn run(&self) -> Result<()> {
        // Connect to both the local Libra node and the backup storage.
        let backup_state =
            metadata::cache::sync_and_load(&self.metadata_cache_opt, Arc::clone(&self.storage))
                .await?
                .get_storage_state();

        // On new DbState retrieved:
        // `watch_db_state` informs `backup_epoch_endings` via channel 1,
        // and the the latter informs the other backup type workers via channel 2, after epoch
        // ending is properly backed up, if necessary. This way, the epoch ending LedgerInfo needed
        // for proof verification is always available in the same backup storage.
        let (tx1, rx1) = watch::channel::<Option<DbState>>(None);
        let (tx2, rx2) = watch::channel::<Option<DbState>>(None);

        // Schedule work streams.
        let watch_db_state = interval(Duration::from_secs(1))
            .then(|_| self.try_refresh_db_state(&tx1))
            .boxed_local();

        let backup_epoch_endings = self
            .backup_work_stream(
                backup_state.latest_epoch_ending_epoch,
                &rx1,
                |slf, last_epoch, db_state| {
                    Self::backup_epoch_endings(slf, last_epoch, db_state, &tx2)
                },
            )
            .boxed_local();
        let backup_state_snapshots = self
            .backup_work_stream(
                backup_state.latest_state_snapshot_version,
                &rx2,
                Self::backup_state_snapshot,
            )
            .boxed_local();
        let backup_transactions = self
            .backup_work_stream(
                backup_state.latest_transaction_version,
                &rx2,
                Self::backup_transactions,
            )
            .boxed_local();

        info!("Backup coordinator started.");
        let mut all_work = stream::select_all(vec![
            watch_db_state,
            backup_epoch_endings,
            backup_state_snapshots,
            backup_transactions,
        ]);

        loop {
            all_work
                .next()
                .await
                .ok_or_else(|| anyhow!("Must be a bug: we never returned None."))?
        }
    }
}

impl BackupCoordinator {
    async fn try_refresh_db_state(&self, db_state_broadcast: &watch::Sender<Option<DbState>>) {
        match self.client.get_db_state().await {
            Ok(s) => {
                if s.is_none() {
                    warn!("DB not bootstrapped.");
                } else {
                    db_state_broadcast
                        .broadcast(s)
                        .map_err(|e| anyhow!("Receivers should not be cancelled: {}", e))
                        .unwrap()
                }
            }
            Err(e) => warn!(
                "Failed pulling DbState from local Libra node: {}. Will keep trying.",
                e
            ),
        };
    }

    async fn backup_epoch_endings(
        &self,
        mut last_epoch_ending_epoch_in_backup: Option<u64>,
        db_state: DbState,
        downstream_db_state_broadcaster: &watch::Sender<Option<DbState>>,
    ) -> Result<Option<u64>> {
        loop {
            let (first, last) = get_batch_range(last_epoch_ending_epoch_in_backup, 1);

            if db_state.epoch <= last {
                // "<=" because `db_state.epoch` hasn't ended yet, wait for the next db_state update
                break;
            }

            EpochEndingBackupController::new(
                EpochEndingBackupOpt {
                    start_epoch: first,
                    end_epoch: last + 1,
                },
                self.global_opt.clone(),
                Arc::clone(&self.client),
                Arc::clone(&self.storage),
            )
            .run()
            .await?;
            last_epoch_ending_epoch_in_backup = Some(last)
        }

        downstream_db_state_broadcaster
            .broadcast(Some(db_state))
            .map_err(|e| anyhow!("Receivers should not be cancelled: {}", e))
            .unwrap();
        Ok(last_epoch_ending_epoch_in_backup)
    }

    async fn backup_state_snapshot(
        &self,
        last_snapshot_version_in_backup: Option<Version>,
        db_state: DbState,
    ) -> Result<Option<Version>> {
        let next_snapshot_version = get_next_snapshot(
            last_snapshot_version_in_backup,
            db_state,
            self.state_snapshot_interval,
        );

        if db_state.committed_version < next_snapshot_version {
            // wait for the next db_state update
            return Ok(last_snapshot_version_in_backup);
        }

        StateSnapshotBackupController::new(
            StateSnapshotBackupOpt {
                version: next_snapshot_version,
            },
            self.global_opt.clone(),
            Arc::clone(&self.client),
            Arc::clone(&self.storage),
        )
        .run()
        .await?;

        Ok(Some(next_snapshot_version))
    }

    async fn backup_transactions(
        &self,
        mut last_transaction_version_in_backup: Option<Version>,
        db_state: DbState,
    ) -> Result<Option<u64>> {
        loop {
            let (first, last) = get_batch_range(
                last_transaction_version_in_backup,
                self.transaction_batch_size,
            );

            if db_state.committed_version < last {
                // wait for the next db_state update
                return Ok(last_transaction_version_in_backup);
            }

            TransactionBackupController::new(
                TransactionBackupOpt {
                    start_version: first,
                    num_transactions: (last + 1 - first) as usize,
                },
                self.global_opt.clone(),
                Arc::clone(&self.client),
                Arc::clone(&self.storage),
            )
            .run()
            .await?;

            last_transaction_version_in_backup = Some(last);
        }
    }

    fn backup_work_stream<'a, S, W, Fut>(
        &'a self,
        initial_state: S,
        db_state_rx: &'a watch::Receiver<Option<DbState>>,
        worker: W,
    ) -> impl StreamExt<Item = ()> + 'a
    where
        S: Copy + Debug + 'a,
        W: Worker<'a, S, Fut> + Copy + 'a,
        Fut: Future<Output = Result<S>> + 'a,
    {
        stream::unfold(
            (initial_state, db_state_rx.clone()),
            move |(s, mut rx)| async move {
                let db_state = rx
                    .recv()
                    .await
                    .ok_or_else(|| anyhow!("The broadcaster has been dropped."))
                    .unwrap();
                if let Some(db_state) = db_state {
                    let next_state = worker(self, s, db_state).await.unwrap_or_else(|e| {
                        warn!("backup failed: {}. Keep trying with state {:?}.", e, s);
                        s
                    });
                    Some(((), (next_state, rx)))
                } else {
                    // initial state
                    Some(((), (s, rx)))
                }
            },
        )
    }
}

trait Worker<'a, S, Fut: Future<Output = Result<S>> + 'a>:
    Fn(&'a BackupCoordinator, S, DbState) -> Fut
{
}

impl<'a, T, S, Fut> Worker<'a, S, Fut> for T
where
    T: Fn(&'a BackupCoordinator, S, DbState) -> Fut,
    Fut: Future<Output = Result<S>> + 'a,
{
}

fn get_batch_range(last_in_backup: Option<u64>, batch_size: usize) -> (u64, u64) {
    // say, 7 is already in backup, and we target batches of size 10, we will return (8, 10) in this
    // case, so 8, 9, 10 will be in this batch, and next time the backup worker will pass in 10,
    // and we will return (11, 20). The transaction 0 will be in it's own batch.
    last_in_backup.map_or((0, 0), |n| {
        let first = n + 1;
        let batch = n / batch_size as u64 + 1;
        let last = batch * batch_size as u64;
        (first, last)
    })
}

fn get_next_snapshot(last_in_backup: Option<u64>, db_state: DbState, interval: usize) -> u64 {
    // We don't try to guarantee snapshots are taken at each applicable interval: when the backup
    // progress can't keep up with the ledger growth, we favor timeliness over completeness.
    // For example, with interval 100, when we finished taking a snapshot at version 700, if we
    // found the latest version is already 1250, the next snapshot we take will be at 1200, not 800.

    let next_for_storage = match last_in_backup {
        Some(last) => (last / interval as u64 + 1) * interval as u64,
        None => 0,
    };

    let last_for_db: u64 = db_state.committed_version / interval as u64 * interval as u64;

    std::cmp::max(next_for_storage, last_for_db)
}

#[cfg(test)]
mod tests {
    use crate::coordinators::backup::{get_batch_range, get_next_snapshot};
    use libradb::backup::backup_handler::DbState;

    #[test]
    fn test_get_batch_range() {
        assert_eq!(get_batch_range(None, 100), (0, 0));
        assert_eq!(get_batch_range(Some(0), 100), (1, 100));
        assert_eq!(get_batch_range(Some(100), 50), (101, 150));
        assert_eq!(get_batch_range(Some(150), 100), (151, 200));
        assert_eq!(get_batch_range(Some(200), 100), (201, 300));
    }

    #[test]
    fn test_get_next_snapshot() {
        let _state = |v| DbState {
            epoch: 0,
            committed_version: v,
            synced_version: v,
        };

        assert_eq!(get_next_snapshot(None, _state(90), 100), 0);
        assert_eq!(get_next_snapshot(Some(0), _state(90), 100), 100);
        assert_eq!(get_next_snapshot(Some(0), _state(190), 100), 100);
        assert_eq!(get_next_snapshot(Some(0), _state(200), 100), 200);
        assert_eq!(get_next_snapshot(Some(0), _state(250), 100), 200);
        assert_eq!(get_next_snapshot(Some(200), _state(250), 100), 300);
    }
}
<|endoftext|>


<commit_before><commit_msg>Shock Wave!<commit_after><|endoftext|>


<commit_before><commit_msg>feat(states): Added states and refactored key press.<commit_after><|endoftext|>


<commit_before><commit_msg>Add dbgprints for creating dm devices<commit_after><|endoftext|>


<commit_before><commit_msg>main.rs: create_display: OpenGL version: 2.0 -> 2.1<commit_after><|endoftext|>


<commit_before><commit_msg>Get test to compile<commit_after><|endoftext|>


<commit_before><commit_msg>fix: panic when using range (unimplemented)<commit_after><|endoftext|>


<commit_before><commit_msg>io -> old_io<commit_after><|endoftext|>


<commit_before><commit_msg>Tweaked spawn and exit messages to match others<commit_after><|endoftext|>


<commit_before><commit_msg>Some panicking<commit_after><|endoftext|>