<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Unix domain sockets.

use std::result::Result;
use std::rc::Rc;
use std::cell::RefCell;
use handle_table::{Handle};
use ::io::{AsyncRead, AsyncWrite, try_read_internal, write_internal,
           FdObserver, HasHandle, register_new_handle,
           Error};
use {EventLoop, Promise, WaitScope};
use private::{with_current_event_loop};

pub struct Stream {
    stream: ::mio::unix::UnixStream,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Stream
}

pub struct Listener {
    listener: ::mio::unix::UnixListener,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Listener
}

impl Drop for Listener {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Listener {
    pub fn bind<P: AsRef<::std::path::Path>>(addr: P) -> Result<Listener, ::std::io::Error> {
        let listener = try!(::mio::unix::UnixListener::bind(&addr));
        let handle = FdObserver::new();

        with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register(&listener, ::mio::Token(handle.val),
                                                                         ::mio::EventSet::readable(),
                                                                         ::mio::PollOpt::edge()));
            Ok(Listener { listener: listener, handle: handle, no_send: ::std::marker::PhantomData })
        })
    }

    fn accept_internal(self) -> Promise<(Listener, Stream), Error<Listener>> {
        let accept_result = match self.listener.accept() {
            Err(e) => return Promise::err((Error::new(self, e))),
            Ok(v) => v,
        };
        match accept_result {
            Some(stream) => {
                let handle = match register_new_handle(&stream) {
                    Err(e) => return Promise::err(Error::new(self, e)),
                    Ok(v) => v,
                };
                Promise::ok((self, Stream::new(stream, handle)))
            }
            None => {
                with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    promise.then_else(move |r| match r {
                        Ok(()) => self.accept_internal(),
                        Err(e) => Promise::err(Error::new(self, e))
                    })
                })
            }
        }
    }

    pub fn accept(self) -> Promise<(Listener, Stream), Error<Listener>> {
        Promise::ok(()).then(move |()| self.accept_internal())
    }
}

impl ::std::io::Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
        use std::io::Read;
        self.stream.read(buf)
    }
}

impl ::std::io::Write for Stream {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
        use std::io::Write;
        self.stream.write(buf)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        use std::io::Write;
        self.stream.flush()
    }
}

impl HasHandle for Stream {
    fn get_handle(&self) -> Handle { self.handle }
}

impl Drop for Stream {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Stream {
    fn new(stream: ::mio::unix::UnixStream, handle: Handle) -> Stream {
        Stream { stream: stream, handle: handle, no_send: ::std::marker::PhantomData }
    }

    pub fn connect<P: AsRef<::std::path::Path>>(addr: P) -> Promise<Stream, ::std::io::Error> {
        let connect_result = ::mio::unix::UnixStream::connect(&addr);
        Promise::ok(()).then(move |()| {
            let stream = pry!(connect_result);

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let handle = pry!(register_new_handle(&stream));

            with_current_event_loop(move |event_loop| {
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                promise.map(move |()| {
                    //try!(stream.take_socket_error());
                    Ok(Stream::new(stream, handle))
                })
            })
        })
    }

    pub fn new_pair() -> Result<(Stream, Stream), ::std::io::Error> {
        use nix::sys::socket::{socketpair, AddressFamily, SockType, SOCK_CLOEXEC, SOCK_NONBLOCK};
        use std::os::unix::io::FromRawFd;

        let (fd1, fd2) =
            try!(socketpair(AddressFamily::Unix, SockType::Stream, 0, SOCK_NONBLOCK | SOCK_CLOEXEC)
                 .map_err(|_| ::std::io::Error::new(::std::io::ErrorKind::Other,
                                                    "failed to create socketpair")));

        unsafe { Ok((try!(Stream::from_raw_fd(fd1)), try!(Stream::from_raw_fd(fd2)))) }
    }

    pub fn try_clone(&self) -> Result<Stream, ::std::io::Error> {
        let stream = try!(self.stream.try_clone());
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }

    pub fn split(self) -> (Reader, Writer) {
        let inner = Rc::new(RefCell::new(self));
        (Reader { stream: inner.clone() }, Writer { stream: inner })
    }

    pub unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Result<Stream, ::std::io::Error> {
        let stream = ::std::os::unix::io::FromRawFd::from_raw_fd(fd);
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }
}

impl AsyncRead for Stream {
    fn try_read<T>(self, buf: T,
                   min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>
    {
        try_read_internal(self, buf, 0, min_bytes)
    }
}

impl AsyncWrite for Stream {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: AsRef<[u8]> {
        write_internal(self, buf, 0)
    }
}

/// Creates a new thread and sets up a socket pair that can be used to communicate with it.
/// Passes one of the sockets to the thread's start function and returns the other socket.
/// The new thread will already have an active event loop when `start_func` is called.
pub fn spawn<F>(start_func: F) -> Result<(::std::thread::JoinHandle<()>, Stream), Box<::std::error::Error>>
    where F: FnOnce(Stream, &WaitScope) -> Result<(), Box<::std::error::Error>>,
          F: Send + 'static
{
    use nix::sys::socket::{socketpair, AddressFamily, SockType, SOCK_CLOEXEC, SOCK_NONBLOCK};
    use std::os::unix::io::FromRawFd;

    let (fd0, fd1) =
        try!(socketpair(AddressFamily::Unix, SockType::Stream, 0, SOCK_NONBLOCK | SOCK_CLOEXEC));

    let socket_stream = try!(unsafe { Stream::from_raw_fd(fd0) });

    let join_handle = ::std::thread::spawn(move || {
        let _result = EventLoop::top_level(move |wait_scope| {
            let socket_stream = try!(unsafe { Stream::from_raw_fd(fd1) });
            start_func(socket_stream, &wait_scope)
        });
    });

    return Ok((join_handle, socket_stream));
}

pub struct Reader {
    stream: Rc<RefCell<Stream>>
}

impl ::std::io::Read for Reader {
    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
        use std::io::Read;
        self.stream.borrow_mut().stream.read(buf)
    }
}

impl HasHandle for Reader {
    fn get_handle(&self) -> Handle { self.stream.borrow().handle }
}

impl AsyncRead for Reader {
    fn try_read<T>(self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>
    {
        try_read_internal(self, buf, 0, min_bytes)
    }
}

pub struct Writer {
    stream: Rc<RefCell<Stream>>
}

impl ::std::io::Write for Writer {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
        use std::io::Write;
        self.stream.borrow_mut().stream.write(buf)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        use std::io::Write;
        self.stream.borrow_mut().flush()
    }
}

impl HasHandle for Writer {
    fn get_handle(&self) -> Handle { self.stream.borrow().handle }
}

impl AsyncWrite for Writer {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: AsRef<[u8]> {
        write_internal(self, buf, 0)
    }
}
<commit_msg>O_NONBLOCK in from_raw_fd()<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Unix domain sockets.

use std::result::Result;
use std::rc::Rc;
use std::cell::RefCell;
use handle_table::{Handle};
use ::io::{AsyncRead, AsyncWrite, try_read_internal, write_internal,
           FdObserver, HasHandle, register_new_handle,
           Error};
use {EventLoop, Promise, WaitScope};
use private::{with_current_event_loop};

pub struct Stream {
    stream: ::mio::unix::UnixStream,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Stream
}

pub struct Listener {
    listener: ::mio::unix::UnixListener,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Listener
}

impl Drop for Listener {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Listener {
    pub fn bind<P: AsRef<::std::path::Path>>(addr: P) -> Result<Listener, ::std::io::Error> {
        let listener = try!(::mio::unix::UnixListener::bind(&addr));
        let handle = FdObserver::new();

        with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register(&listener, ::mio::Token(handle.val),
                                                                         ::mio::EventSet::readable(),
                                                                         ::mio::PollOpt::edge()));
            Ok(Listener { listener: listener, handle: handle, no_send: ::std::marker::PhantomData })
        })
    }

    fn accept_internal(self) -> Promise<(Listener, Stream), Error<Listener>> {
        let accept_result = match self.listener.accept() {
            Err(e) => return Promise::err((Error::new(self, e))),
            Ok(v) => v,
        };
        match accept_result {
            Some(stream) => {
                let handle = match register_new_handle(&stream) {
                    Err(e) => return Promise::err(Error::new(self, e)),
                    Ok(v) => v,
                };
                Promise::ok((self, Stream::new(stream, handle)))
            }
            None => {
                with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    promise.then_else(move |r| match r {
                        Ok(()) => self.accept_internal(),
                        Err(e) => Promise::err(Error::new(self, e))
                    })
                })
            }
        }
    }

    pub fn accept(self) -> Promise<(Listener, Stream), Error<Listener>> {
        Promise::ok(()).then(move |()| self.accept_internal())
    }
}

impl ::std::io::Read for Stream {
    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
        use std::io::Read;
        self.stream.read(buf)
    }
}

impl ::std::io::Write for Stream {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
        use std::io::Write;
        self.stream.write(buf)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        use std::io::Write;
        self.stream.flush()
    }
}

impl HasHandle for Stream {
    fn get_handle(&self) -> Handle { self.handle }
}

impl Drop for Stream {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Stream {
    fn new(stream: ::mio::unix::UnixStream, handle: Handle) -> Stream {
        Stream { stream: stream, handle: handle, no_send: ::std::marker::PhantomData }
    }

    pub fn connect<P: AsRef<::std::path::Path>>(addr: P) -> Promise<Stream, ::std::io::Error> {
        let connect_result = ::mio::unix::UnixStream::connect(&addr);
        Promise::ok(()).then(move |()| {
            let stream = pry!(connect_result);

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let handle = pry!(register_new_handle(&stream));

            with_current_event_loop(move |event_loop| {
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                promise.map(move |()| {
                    //try!(stream.take_socket_error());
                    Ok(Stream::new(stream, handle))
                })
            })
        })
    }

    pub fn new_pair() -> Result<(Stream, Stream), ::std::io::Error> {
        use nix::sys::socket::{socketpair, AddressFamily, SockType, SOCK_CLOEXEC, SOCK_NONBLOCK};
        use std::os::unix::io::FromRawFd;

        let (fd1, fd2) =
            try!(socketpair(AddressFamily::Unix, SockType::Stream, 0, SOCK_NONBLOCK | SOCK_CLOEXEC)
                 .map_err(|_| ::std::io::Error::new(::std::io::ErrorKind::Other,
                                                    "failed to create socketpair")));

        unsafe { Ok((try!(Stream::from_raw_fd(fd1)), try!(Stream::from_raw_fd(fd2)))) }
    }

    pub fn try_clone(&self) -> Result<Stream, ::std::io::Error> {
        let stream = try!(self.stream.try_clone());
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }

    pub fn split(self) -> (Reader, Writer) {
        let inner = Rc::new(RefCell::new(self));
        (Reader { stream: inner.clone() }, Writer { stream: inner })
    }

    /// Consumes a raw file descriptor to creates a `Stream`. Ensures that O_NONBLOCK is set on the
    /// descriptor.
    pub unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Result<Stream, ::std::io::Error> {
        try!(::nix::fcntl::fcntl(fd, ::nix::fcntl::FcntlArg::F_SETFL(::nix::fcntl::O_NONBLOCK)));
        let stream = ::std::os::unix::io::FromRawFd::from_raw_fd(fd);
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }
}

impl AsyncRead for Stream {
    fn try_read<T>(self, buf: T,
                   min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>
    {
        try_read_internal(self, buf, 0, min_bytes)
    }
}

impl AsyncWrite for Stream {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: AsRef<[u8]> {
        write_internal(self, buf, 0)
    }
}

/// Creates a new thread and sets up a socket pair that can be used to communicate with it.
/// Passes one of the sockets to the thread's start function and returns the other socket.
/// The new thread will already have an active event loop when `start_func` is called.
pub fn spawn<F>(start_func: F) -> Result<(::std::thread::JoinHandle<()>, Stream), Box<::std::error::Error>>
    where F: FnOnce(Stream, &WaitScope) -> Result<(), Box<::std::error::Error>>,
          F: Send + 'static
{
    use nix::sys::socket::{socketpair, AddressFamily, SockType, SOCK_CLOEXEC, SOCK_NONBLOCK};
    use std::os::unix::io::FromRawFd;

    let (fd0, fd1) =
        try!(socketpair(AddressFamily::Unix, SockType::Stream, 0, SOCK_NONBLOCK | SOCK_CLOEXEC));

    let socket_stream = try!(unsafe { Stream::from_raw_fd(fd0) });

    let join_handle = ::std::thread::spawn(move || {
        let _result = EventLoop::top_level(move |wait_scope| {
            let socket_stream = try!(unsafe { Stream::from_raw_fd(fd1) });
            start_func(socket_stream, &wait_scope)
        });
    });

    return Ok((join_handle, socket_stream));
}

pub struct Reader {
    stream: Rc<RefCell<Stream>>
}

impl ::std::io::Read for Reader {
    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
        use std::io::Read;
        self.stream.borrow_mut().stream.read(buf)
    }
}

impl HasHandle for Reader {
    fn get_handle(&self) -> Handle { self.stream.borrow().handle }
}

impl AsyncRead for Reader {
    fn try_read<T>(self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>
    {
        try_read_internal(self, buf, 0, min_bytes)
    }
}

pub struct Writer {
    stream: Rc<RefCell<Stream>>
}

impl ::std::io::Write for Writer {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
        use std::io::Write;
        self.stream.borrow_mut().stream.write(buf)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        use std::io::Write;
        self.stream.borrow_mut().flush()
    }
}

impl HasHandle for Writer {
    fn get_handle(&self) -> Handle { self.stream.borrow().handle }
}

impl AsyncWrite for Writer {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: AsRef<[u8]> {
        write_internal(self, buf, 0)
    }
}
<|endoftext|>


<commit_before>//! Implements polynomial operations in GF(2^8).

use std::error::Error;

use gf256::{div, mul};

/// Evaluate a polynomial, returning the Y value for the given X value.
pub fn eval(p: &[u8], x: u8) -> u8 {
    p.iter().rev().fold(0u8, |res, &v| mul(res, x) ^ v)
}

/// Generates a random polynomial of the Nth degree with a Y-intercept with the
/// given value.
pub fn generate<E, T>(n: usize, y: u8, rng: T) -> Vec<u8>
where
    E: Error,
    T: Fn(&mut [u8]) -> Result<(), E>,
{
    let mut p = vec![0; n + 1];

    // Set its Y-intercept to the given value.
    p[0] = y;

    // Generate random coefficients.
    rng(&mut p[1..]).unwrap();

    // Ensure the Nth coefficient is non-zero, otherwise it's an (N-1)th-degree
    // polynomial.
    while p[n] == 0 {
        rng(&mut p[n..=n]).unwrap();
    }
    p
}

/// Interpolates a vector of (X, Y) points, returning the Y value at zero.
pub fn y_intercept(points: Vec<(u8, u8)>) -> u8 {
    let mut value = 0u8;
    for (i, &(ax, ay)) in points.iter().enumerate() {
        let mut weight = 1u8;
        for (j, &(bx, _)) in points.iter().enumerate() {
            if i != j {
                weight = mul(weight, div(bx, ax ^ bx));
            }
        }
        value ^= mul(weight, ay)
    }
    value
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_eval() {
        assert_eq!(eval(&vec![1, 0, 2, 3], 2), 17);
    }

    #[test]
    fn test_generate() {
        assert_eq!(generate(5, 50, fake_getrandom), vec![50, 1, 0, 0, 0, 1])
    }

    fn fake_getrandom(dest: &mut [u8]) -> Result<(), std::io::Error> {
        dest[0] = 1;
        for x in 1..dest.len() {
            dest[x] = 0;
        }
        return Ok(());
    }

    #[test]
    fn test_y_intercept() {
        assert_eq!(y_intercept(vec![(1, 1), (2, 2), (3, 3)]), 0);
        assert_eq!(y_intercept(vec![(1, 80), (2, 90), (3, 20)]), 30);
        assert_eq!(y_intercept(vec![(1, 43), (2, 22), (3, 86)]), 107);
    }
}
<commit_msg>Simplify unbounded range.<commit_after>//! Implements polynomial operations in GF(2^8).

use std::error::Error;

use gf256::{div, mul};

/// Evaluate a polynomial, returning the Y value for the given X value.
pub fn eval(p: &[u8], x: u8) -> u8 {
    p.iter().rev().fold(0u8, |res, &v| mul(res, x) ^ v)
}

/// Generates a random polynomial of the Nth degree with a Y-intercept with the
/// given value.
pub fn generate<E, T>(n: usize, y: u8, rng: T) -> Vec<u8>
where
    E: Error,
    T: Fn(&mut [u8]) -> Result<(), E>,
{
    let mut p = vec![0; n + 1];

    // Set its Y-intercept to the given value.
    p[0] = y;

    // Generate random coefficients.
    rng(&mut p[1..]).unwrap();

    // Ensure the Nth coefficient is non-zero, otherwise it's an (N-1)th-degree
    // polynomial.
    while p[n] == 0 {
        rng(&mut p[n..]).unwrap();
    }
    p
}

/// Interpolates a vector of (X, Y) points, returning the Y value at zero.
pub fn y_intercept(points: Vec<(u8, u8)>) -> u8 {
    let mut value = 0u8;
    for (i, &(ax, ay)) in points.iter().enumerate() {
        let mut weight = 1u8;
        for (j, &(bx, _)) in points.iter().enumerate() {
            if i != j {
                weight = mul(weight, div(bx, ax ^ bx));
            }
        }
        value ^= mul(weight, ay)
    }
    value
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_eval() {
        assert_eq!(eval(&vec![1, 0, 2, 3], 2), 17);
    }

    #[test]
    fn test_generate() {
        assert_eq!(generate(5, 50, fake_getrandom), vec![50, 1, 0, 0, 0, 1])
    }

    fn fake_getrandom(dest: &mut [u8]) -> Result<(), std::io::Error> {
        dest[0] = 1;
        for x in 1..dest.len() {
            dest[x] = 0;
        }
        return Ok(());
    }

    #[test]
    fn test_y_intercept() {
        assert_eq!(y_intercept(vec![(1, 1), (2, 2), (3, 3)]), 0);
        assert_eq!(y_intercept(vec![(1, 80), (2, 90), (3, 20)]), 30);
        assert_eq!(y_intercept(vec![(1, 43), (2, 22), (3, 86)]), 107);
    }
}
<|endoftext|>


<commit_before>//!A raytracer.
#![feature(path, io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;

use rand::distributions::IndependentSample;
use rand::Rng;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection<ObjectId> {
    time: f32,
    point: Point3,
    normal: Vec3,
    emitted: f32,
    object: ObjectId
}

trait Scene {
    // TODO: Should this have a "not present" id?
    type ObjectId: Copy;

    fn intersect(&self, ray: Ray3, previous: Option<Self::ObjectId>) -> Option<Intersection<Self::ObjectId>>;
}

struct Material {
    emitted_radiance: f32
}

struct Sphere {
    center: Point3,
    radius: f32,
    material: Material
}

impl Scene for Sphere {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > 0. {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else if t2 > 0. {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3,
    material: Material
}

impl Scene for Plane {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        }
    }
}

#[derive(Copy)]
enum Choice<A, B> {
    OptA(A),
    OptB(B)
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    type ObjectId = Choice<A::ObjectId, B::ObjectId>;
    fn intersect(&self, ray: Ray3, previous: Option<Choice<A::ObjectId, B::ObjectId>>) -> Option<Intersection<Choice<A::ObjectId, B::ObjectId>>> {
        let (aid, bid) = match previous {
            None => (None, None),
            Some(Choice::OptA(aid)) => (Some(aid), None),
            Some(Choice::OptB(bid)) => (None, Some(bid))
        };

        match self.0.intersect(ray, aid) {
            Some(ai) => {
                match self.1.intersect(ray, bid) {
                    Some(bi) => if ai.time < bi.time {
                        Some(Intersection {
                            time: ai.time,
                            normal: ai.normal,
                            point: ai.point,
                            emitted: ai.emitted,
                            object: Choice::OptA(ai.object)
                        })
                    } else {
                        Some(Intersection {
                            time: bi.time,
                            normal: bi.normal,
                            point: bi.point,
                            emitted: bi.emitted,
                            object: Choice::OptB(bi.object)
                        })
                    },
                    None => Some(Intersection {
                        time: ai.time,
                        normal: ai.normal,
                        point: ai.point,
                        emitted: ai.emitted,
                        object: Choice::OptA(ai.object)
                    })
                }
            },
            None => match self.1.intersect(ray, bid) {
                Some(bi) => Some(Intersection {
                    time: bi.time,
                    normal: bi.normal,
                    point: bi.point,
                    emitted: bi.emitted,
                    object: Choice::OptB(bi.object)
                }),
                None => None
            }
        }
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let mut rng = rand::thread_rng();

    let rays_per_pixel = 100;
    let scene = (
        ((Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { emitted_radiance: 0. }
        }),
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { emitted_radiance: 20. }
        }),
        ((Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { emitted_radiance: 0. }
        }),
        (Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        }))
    );

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            let mut prev_object = None;
            let mut scale = 1.;
            loop {
                if let Some(intersection) = scene.intersect(ray, prev_object) {
                    prev_object = Some(intersection.object);

                    total_light += scale * intersection.emitted;

                    let cand_dir = rand_sphere(&mut rng);
                    let dir = if cand_dir.dot(intersection.normal) < 0. {
                        -cand_dir
                    } else {
                        cand_dir
                    };
                    ray = Ray3 {
                        start: intersection.point,
                        dir: dir
                    };

                    let p = dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                    if scale > 0.2 {
                        scale *= p;
                    } else if rng.next_f32() > p {
                        break;
                    }
                } else {
                    break;
                }
            }
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(clamp(total_light / rays_per_pixel as f32)*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<commit_msg>Use arrays instead of just tuples. This is slightly faster.<commit_after>//!A raytracer.
#![feature(path, io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;

use rand::distributions::IndependentSample;
use rand::Rng;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection<ObjectId> {
    time: f32,
    point: Point3,
    normal: Vec3,
    emitted: f32,
    object: ObjectId
}

trait Scene {
    // TODO: Should this have a "not present" id?
    type ObjectId: Copy;

    fn intersect(&self, ray: Ray3, previous: Option<Self::ObjectId>) -> Option<Intersection<Self::ObjectId>>;
}

struct Material {
    emitted_radiance: f32
}

struct Sphere {
    center: Point3,
    radius: f32,
    material: Material
}

impl Scene for Sphere {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > 0. {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else if t2 > 0. {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3,
    material: Material
}

impl Scene for Plane {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        }
    }
}

#[derive(Copy)]
enum Choice<A, B> {
    OptA(A),
    OptB(B)
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    type ObjectId = Choice<A::ObjectId, B::ObjectId>;
    fn intersect(&self, ray: Ray3, previous: Option<Choice<A::ObjectId, B::ObjectId>>) -> Option<Intersection<Choice<A::ObjectId, B::ObjectId>>> {
        let (aid, bid) = match previous {
            None => (None, None),
            Some(Choice::OptA(aid)) => (Some(aid), None),
            Some(Choice::OptB(bid)) => (None, Some(bid))
        };

        match self.0.intersect(ray, aid) {
            Some(ai) => {
                match self.1.intersect(ray, bid) {
                    Some(bi) => if ai.time < bi.time {
                        Some(Intersection {
                            time: ai.time,
                            normal: ai.normal,
                            point: ai.point,
                            emitted: ai.emitted,
                            object: Choice::OptA(ai.object)
                        })
                    } else {
                        Some(Intersection {
                            time: bi.time,
                            normal: bi.normal,
                            point: bi.point,
                            emitted: bi.emitted,
                            object: Choice::OptB(bi.object)
                        })
                    },
                    None => Some(Intersection {
                        time: ai.time,
                        normal: ai.normal,
                        point: ai.point,
                        emitted: ai.emitted,
                        object: Choice::OptA(ai.object)
                    })
                }
            },
            None => match self.1.intersect(ray, bid) {
                Some(bi) => Some(Intersection {
                    time: bi.time,
                    normal: bi.normal,
                    point: bi.point,
                    emitted: bi.emitted,
                    object: Choice::OptB(bi.object)
                }),
                None => None
            }
        }
    }
}

impl<T: Scene> Scene for [T] {
    type ObjectId = (usize, T::ObjectId);
    fn intersect(&self, ray: Ray3, previous: Option<(usize, T::ObjectId)>) -> Option<Intersection<(usize, T::ObjectId)>> {
        let mut best: Option<Intersection<(usize, T::ObjectId)>> = None;

        for (id, obj) in self.iter().enumerate() {
            let prev = match previous {
                Some((prev_index, prev_obj)) => if prev_index == id {
                    Some(prev_obj)
                } else {
                    None
                },
                None => None
            };

            if let Some(intersection) = obj.intersect(ray, prev) {
                let new_best = match best {
                    Some(ref cur_best) => intersection.time < cur_best.time,
                    None => true
                };

                if new_best {
                    best = Some(Intersection {
                        time: intersection.time,
                        normal: intersection.normal,
                        point: intersection.point,
                        emitted: intersection.emitted,
                        object: (id, intersection.object)
                    });
                }
            }
        }

        best
    }
}

impl<'a, T: ?Sized + Scene> Scene for &'a T {
    type ObjectId = T::ObjectId;
    fn intersect(&self, ray: Ray3, previous: Option<T::ObjectId>) -> Option<Intersection<T::ObjectId>> {
        (*self).intersect(ray, previous)
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let mut rng = rand::thread_rng();

    let rays_per_pixel = 100;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { emitted_radiance: 20. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        }]
    );

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            let mut prev_object = None;
            let mut scale = 1.;
            loop {
                if let Some(intersection) = scene.intersect(ray, prev_object) {
                    prev_object = Some(intersection.object);

                    total_light += scale * intersection.emitted;

                    let cand_dir = rand_sphere(&mut rng);
                    let dir = if cand_dir.dot(intersection.normal) < 0. {
                        -cand_dir
                    } else {
                        cand_dir
                    };
                    ray = Ray3 {
                        start: intersection.point,
                        dir: dir
                    };

                    let p = dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                    if scale > 0.2 {
                        scale *= p;
                    } else if rng.next_f32() > p {
                        break;
                    }
                } else {
                    break;
                }
            }
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(clamp(total_light / rays_per_pixel as f32)*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! syslog {
    ($level:path, $msg:expr) => {
        unsafe {
            libc::openlog("sectora".as_ptr() as *const libc::c_char, libc::LOG_PID, libc::LOG_AUTH);
            libc::syslog($level, $msg.as_ptr() as *const libc::c_char);
            libc::closelog();
        }
    };
}
<commit_msg>Remove the naive impl<commit_after><|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;
use std::cell::RefCell;

struct Rlru<K, V>
    where K: Eq + Hash
{
    cache: HashMap<K, Rc<RefCell<Node<V>>>>,
    head: Link<V>,
    tail: Link<V>,
    max_length: u32,
}

struct Node<T> {
    elem: T,
    prev: Link<T>,
    next: Link<T>,
}

impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Node {
            elem: elem,
            prev: None,
            next: None,
        }
    }
}

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

impl<K, V> Rlru<K, V>
    where K: Eq + Hash
{
    pub fn new() -> Self {
        Rlru {
            cache: HashMap::new(),
            head: None,
            tail: None,
            max_length: 0,
        }
    }

    fn length_upkeep(&mut self) -> &mut Self {
        match self.cache.len() {
            len if len < self.max_length as usize => self,
            // placeholder. Will pop off LRU key.
            _ => self
        }
    }

    fn splice_node(&mut self, node: Rc<RefCell<Node<V>>>) {
        // update node's prev/next pointers to link to each other
        {
            let mut node = node.borrow_mut();

            // First we use cloning via Rc pointers, but will clean up our references via 'take' in the next_node routine
            node.prev.clone().map(|prev_node| {
                prev_node.borrow_mut().next = node.next.clone();
            });

            // here we take the extracted node's remaining pointers.
            node.next.take().map(|next_node| {
                next_node.borrow_mut().prev = node.prev.take();
            });
        }

        // insert node at head of rlru.
        self.push(node);
    }

    fn push(&mut self, node: Rc<RefCell<Node<V>>>) -> &mut Self {
        self.head.take().map(|prev_head| {
            prev_head.borrow_mut().prev = Some(node.clone());
            node.borrow_mut().next = Some(prev_head);
        });
        self.head = Some(node.clone());
        self
    }

    fn pop(&mut self) {
        self.tail.take().map(|node| {
            if node.borrow().prev.is_none() {
                // have to worry about updating head.
                self.head.take();
            }
            self.tail = node.borrow_mut().prev.take();
        });
    }

    pub fn get<'a>(&'a mut self, key: K) -> Option<&'a V> {
        match self.cache.entry(key) {
            Entry::Occupied(entry) => {
                // splice node to front
                let found = entry.get();
                self.splice_node(found.clone());
                Some(&found.as_ref().borrow().elem)
            },
            Entry::Vacant(_) => None
        }
    }

    pub fn set(&mut self, key: K, elem: V) -> &mut Self {
        match self.cache.entry(key) {
            Entry::Occupied(node) => {
                // splice node to front & update value
                self
            },
            Entry::Vacant(_) =>  {
                // insert node to front & do ln upkeep
                self
            }
        }
    }
}
<commit_msg>get method with std::cell::Ref. Should investigate borrow trait next<commit_after>use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;
use std::cell::{RefCell, Ref};

struct Rlru<K, V>
    where K: Eq + Hash + Clone
{
    cache: HashMap<K, Rc<RefCell<Node<V>>>>,
    head: Link<V>,
    tail: Link<V>,
    max_length: u32,
}

struct Node<T> {
    elem: T,
    prev: Link<T>,
    next: Link<T>,
}

impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Node {
            elem: elem,
            prev: None,
            next: None,
        }
    }
}

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

impl<K, V> Rlru<K, V>
    where K: Eq + Hash + Clone
{
    pub fn new() -> Self {
        Rlru {
            cache: HashMap::new(),
            head: None,
            tail: None,
            max_length: 0,
        }
    }

    fn length_upkeep(&mut self) -> &mut Self {
        match self.cache.len() {
            len if len < self.max_length as usize => self,
            // placeholder. Will pop off LRU key.
            _ => self
        }
    }

    fn splice_node(&mut self, node: Rc<RefCell<Node<V>>>) {
        // update node's prev/next pointers to link to each other
        {
            let mut node = node.borrow_mut();

            // First we use cloning via Rc pointers, but will clean up our references via 'take' in the next_node routine
            node.prev.clone().map(|prev_node| {
                prev_node.borrow_mut().next = node.next.clone();
            });

            // here we take the extracted node's remaining pointers.
            node.next.take().map(|next_node| {
                next_node.borrow_mut().prev = node.prev.take();
            });
        }

        // insert node at head of rlru.
        self.push(node);
    }

    fn push(&mut self, node: Rc<RefCell<Node<V>>>) -> &mut Self {
        self.head.take().map(|prev_head| {
            prev_head.borrow_mut().prev = Some(node.clone());
            node.borrow_mut().next = Some(prev_head);
        });
        self.head = Some(node.clone());
        self
    }

    fn pop(&mut self) {
        self.tail.take().map(|node| {
            if node.borrow().prev.is_none() {
                // have to worry about updating head.
                self.head.take();
            }
            self.tail = node.borrow_mut().prev.take();
        });
    }

    pub fn get(&mut self, key: K) -> Option<Ref<V>> {
        if let Some(node) = self.cache.remove(&key) {
            self.splice_node(node.clone());
            self.cache.insert(key.clone(), node);
            self.cache.get(&key).map(|node| {
                Ref::map(node.as_ref().borrow(), |x| &x.elem)
            })
        } else {
            None
        }

    }

    pub fn set(&mut self, key: K, elem: V) -> &mut Self {
        match self.cache.entry(key) {
            Entry::Occupied(node) => {
                // splice node to front & update value
                self
            },
            Entry::Vacant(_) =>  {
                // insert node to front & do ln upkeep
                self
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
}<commit_msg>Add two tests for elementwise multiplication<commit_after>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
}<|endoftext|>


<commit_before>//! Traits, implementations, and macros related to logging timely events.

use std::io::Write;
use std::rc::Rc;
use std::sync::{Arc, Mutex};

use std::collections::HashMap;
use std::fmt::Debug;

use ::progress::timestamp::RootTimestamp;
use ::progress::nested::product::Product;

use dataflow::operators::capture::{EventWriter, Event, EventPusher};

use abomonation::Abomonation;

use std::net::TcpStream;

use timely_logging::BufferingLogger;
use timely_logging::Event as LogEvent;
use timely_logging::EventsSetup;
use timely_logging::{CommsEvent, CommsSetup};
use timely_logging::LoggerBatch;

type LogMessage = (u64, EventsSetup, LogEvent);
type CommsMessage = (u64, CommsSetup, CommsEvent);

/// TODO(andreal)
pub type Logger = Rc<BufferingLogger<EventsSetup, LogEvent>>;

/// TODO(andreal)
pub fn new_inactive_logger() -> Logger {
    BufferingLogger::<(), ()>::new_inactive()
}

/// TODO(andreal)
pub struct LogManager {
    timely_logs: HashMap<
        EventsSetup,
        Arc<Mutex<EventStreamSubscriptionManager<EventsSetup, LogEvent>>>>,
    timely_subscriptions:
        Vec<(Arc<Fn(&EventsSetup)->bool+Send+Sync>, Arc<EventPusher<Product<RootTimestamp, u64>, LogMessage>+Send+Sync>)>,
    communication_logs: HashMap<
        CommsSetup,
        Arc<Mutex<EventStreamSubscriptionManager<CommsSetup, CommsEvent>>>>,
    communication_subscriptions:
        Vec<(Arc<Fn(&CommsSetup)->bool+Send+Sync>, Arc<EventPusher<Product<RootTimestamp, u64>, CommsMessage>+Send+Sync>)>,
}

impl LogManager {
    fn add_timely_subscription(&mut self,
                               filter: Arc<Fn(&EventsSetup)->bool+Send+Sync>,
                               pusher: Arc<EventPusher<Product<RootTimestamp, u64>, LogMessage>+Send+Sync>) {

        pusher.push(Event::Progress(vec![(Default::default(), -1)]));
        for (_, ref event_manager) in self.timely_logs.iter().filter(|&(ref setup, _)| filter(setup)) {
            event_manager.lock().unwrap().subscribe(pusher.clone());
        }
        self.timely_subscriptions.push((filter, pusher));
    }

    fn add_communication_subscription(&mut self,
                                      filter: Arc<Fn(&CommsSetup)->bool+Send+Sync>,
                                      pusher: Arc<EventPusher<Product<RootTimestamp, u64>, CommsMessage>+Send+Sync>) {

        //eprintln!("new comm subscription");
        pusher.push(Event::Progress(vec![(Default::default(), -1)]));
        for (_, ref event_manager) in self.communication_logs.iter().filter(|&(ref setup, _)| filter(setup)) {
            //eprintln!("  to comm logger {:?}", setup);
            event_manager.lock().unwrap().subscribe(pusher.clone());
        }
        self.communication_subscriptions.push((filter, pusher));
    }
}

struct SharedVec {
    inner: Arc<Mutex<Vec<u8>>>,
}

impl SharedVec {
    pub fn new(inner: Arc<Mutex<Vec<u8>>>) -> Self {
        SharedVec {
            inner: inner,
        }
    }
}

impl Write for SharedVec {
    fn write(&mut self, data: &[u8]) -> Result<usize, ::std::io::Error> {
        self.inner.lock().unwrap().extend_from_slice(data);
        Ok(data.len())
    }

    fn flush(&mut self) -> Result<(), ::std::io::Error> {
        Ok(())
    }
}

struct SharedEventWriter<T, D, W: Write> {
    inner: Mutex<EventWriter<T, D, W>>,
}

impl<T, D, W: Write> SharedEventWriter<T, D, W> {
    fn new(w: W) -> Self {
        SharedEventWriter {
            inner: Mutex::new(EventWriter::new(w)),
        }
    }
}

impl<T: Abomonation+Debug, D: Abomonation+Debug, W: Write> EventPusher<T, D> for SharedEventWriter<T, D, W> {
    fn push(&self, event: Event<T, D>) {
        let inner = self.inner.lock().expect("event pusher poisoned");
        inner.push(event)
    }
}

/// TODO(andreal)
pub struct FilteredLogManager<S, E> {
    log_manager: Arc<Mutex<LogManager>>,
    filter: Arc<Fn(&S)->bool+Send+Sync>,
    _e: ::std::marker::PhantomData<E>,
}

impl FilteredLogManager<EventsSetup, LogEvent> {
    /// TODO(andreal)
    pub fn to_tcp_socket(&mut self) {
        let target: String = ::std::env::var("TIMELY_LOG_TARGET").expect("no $TIMELY_LOG_TARGET, e.g. 127.0.0.1:34254");
        let writer = /*BufWriter::with_capacity(4096,*/ TcpStream::connect(target).expect("failed to connect to logging destination"); //);

        let writer = SharedEventWriter::new(writer);
        let pusher: Arc<EventPusher<Product<RootTimestamp, u64>, LogMessage>+Send+Sync> = Arc::new(writer);

        self.log_manager.lock().unwrap().add_timely_subscription(self.filter.clone(), pusher);
    }

    /// TODO(andreal)
    pub fn to_bufs(&mut self) -> Vec<Arc<Mutex<Vec<u8>>>> {
        let mut vecs = Vec::new();

        for i in 0..4 {
            let buf = Arc::new(Mutex::new(Vec::<u8>::with_capacity(4_000_000_000)));
            let writer = SharedEventWriter::new(SharedVec::new(buf.clone()));
            let pusher: Arc<EventPusher<Product<RootTimestamp, u64>, LogMessage>+Send+Sync> = Arc::new(writer);
            self.log_manager.lock().unwrap().add_timely_subscription(Arc::new(move |s| s.index == i), pusher);
            vecs.push(buf);
        }

        vecs
    }
}

impl FilteredLogManager<CommsSetup, CommsEvent> {
    /// TODO(andreal)
    pub fn to_tcp_socket(&mut self) {
        let comm_target = ::std::env::var("TIMELY_COMM_LOG_TARGET").expect("no $TIMELY_COMM_LOG_TARGET, e.g. 127.0.0.1:34255");
        let writer = /* BufWriter::with_capacity(4096,*/ TcpStream::connect(comm_target).expect("failed to connect to logging destination"); //);

        let writer = SharedEventWriter::new(writer);
        let pusher: Arc<EventPusher<Product<RootTimestamp, u64>, CommsMessage>+Send+Sync> = Arc::new(writer);

        self.log_manager.lock().unwrap().add_communication_subscription(self.filter.clone(), pusher);
    }
}

impl LogManager {
    /// TODO(andreal)
    pub fn new() -> Arc<Mutex<Self>> {
        Arc::new(Mutex::new(LogManager {
            timely_logs: HashMap::new(),
            timely_subscriptions: Vec::new(),
            communication_logs: HashMap::new(),
            communication_subscriptions: Vec::new(),
        }))
    }
}

/// TODO(andreal)
pub trait LogFilter {
    /// TODO(andreal)
    fn workers(&mut self) -> FilteredLogManager<EventsSetup, LogEvent>;

    /// TODO(andreal)
    fn comms(&mut self) -> FilteredLogManager<CommsSetup, CommsEvent>;
}

impl LogFilter for Arc<Mutex<LogManager>> {
    /// TODO(andreal)
    #[inline] fn workers(&mut self) -> FilteredLogManager<EventsSetup, LogEvent> {
        FilteredLogManager {
            log_manager: self.clone(),
            filter: Arc::new(|_| true),
            _e: ::std::marker::PhantomData,
        }
    }

    /// TODO(andreal)
    #[inline] fn comms(&mut self) -> FilteredLogManager<CommsSetup, CommsEvent> {
        FilteredLogManager {
            log_manager: self.clone(),
            filter: Arc::new(|_| true),
            _e: ::std::marker::PhantomData,
        }
    }
}

/// TODO(andreal)
pub struct LoggerConfig {
    /// TODO(andreal)
    pub timely_logging: Arc<Fn(EventsSetup)->Rc<BufferingLogger<EventsSetup, LogEvent>>+Send+Sync>,
    /// TODO(andreal)
    pub communication_logging: Arc<Fn(CommsSetup)->Rc<BufferingLogger<CommsSetup, CommsEvent>>+Send+Sync>,
}

impl LoggerConfig {
    fn register_timely_logger(
        log_manager: &mut LogManager,
        events_setup: EventsSetup) -> Arc<Mutex<EventStreamSubscriptionManager<EventsSetup, LogEvent>>> {

        let event_manager: Arc<Mutex<EventStreamSubscriptionManager<EventsSetup, LogEvent>>> = Arc::new(Mutex::new(Default::default()));
        log_manager.timely_logs.insert(events_setup, event_manager.clone());
        for pusher in log_manager.timely_subscriptions.iter().filter(|&&(ref f, _)| f(&events_setup)).map(|&(_, ref p)| p.clone()) {
            event_manager.lock().unwrap().subscribe(pusher);
        }
        println!("pushers: {}", event_manager.lock().unwrap().event_pushers.len());
        event_manager
    }

    fn register_comms_logger(
        log_manager: &mut LogManager,
        comms_setup: CommsSetup) -> Arc<Mutex<EventStreamSubscriptionManager<CommsSetup, CommsEvent>>> {

        let event_manager: Arc<Mutex<EventStreamSubscriptionManager<CommsSetup, CommsEvent>>> = Arc::new(Mutex::new(Default::default()));
        log_manager.communication_logs.insert(comms_setup, event_manager.clone());
        for pusher in log_manager.communication_subscriptions.iter().filter(|&&(ref f, _)| f(&comms_setup)).map(|&(_, ref p)| p.clone()) {
            event_manager.lock().unwrap().subscribe(pusher);
        }
        event_manager
    }

    /// TODO(andreal)
    pub fn new(log_manager: Arc<Mutex<LogManager>>) -> Self {
        let timely_logging_manager = log_manager.clone();
        let communication_logging_manager = log_manager;
        LoggerConfig {
            timely_logging: Arc::new(move |events_setup: EventsSetup| {
                let subscription_manager = LoggerConfig::register_timely_logger(
                    &mut timely_logging_manager.lock().unwrap(), events_setup);
                //eprintln!("registered timely logger: {:?}", events_setup);
                Rc::new(BufferingLogger::new(events_setup, Box::new(move |data| {
                    subscription_manager.lock().expect("cannot lock mutex").publish_batch(data);
                })))
            }),
            communication_logging: Arc::new(move |comms_setup: CommsSetup| {
                let subscription_manager = LoggerConfig::register_comms_logger(
                    &mut communication_logging_manager.lock().unwrap(), comms_setup);
                //eprintln!("registered comm logger: {:?}", comms_setup);
                Rc::new(BufferingLogger::new(comms_setup, Box::new(move |data| {
                    subscription_manager.lock().expect("cannot lock mutex").publish_batch(data);
                })))
            }),
        }
    }
}

impl Default for LoggerConfig {
    fn default() -> Self {
        LoggerConfig {
            timely_logging: Arc::new(|setup| Rc::new(BufferingLogger::new(setup, Box::new(|_| {})))),
            communication_logging: Arc::new(|setup| Rc::new(BufferingLogger::new(setup, Box::new(|_| {})))),
        }
    }
}

struct EventStreamSubscriptionManager<S, E> {
    // None when the logging stream is closed
    frontier: Option<Product<RootTimestamp, u64>>,
    event_pushers: Vec<Arc<EventPusher<Product<RootTimestamp, u64>, (u64, S, E)>+Send+Sync>>,
}

impl<S, E> Default for EventStreamSubscriptionManager<S, E> {
    fn default() -> Self {
        EventStreamSubscriptionManager {
            frontier: Some(Default::default()),
            event_pushers: Vec::new(),
        }
    }
}

impl<S: Clone, E: Clone> EventStreamSubscriptionManager<S, E> {
    fn subscribe(&mut self, pusher: Arc<EventPusher<Product<RootTimestamp, u64>, (u64, S, E)>+Send+Sync>) {
        //eprintln!("pusher subscription to logger");
        // if this logging stream is already closed
        if let Some(frontier) = self.frontier {
            pusher.push(Event::Progress(vec![(frontier, 1)]));
        } else {
            eprintln!("logging: subscription to closed stream");
        }
        self.event_pushers.push(pusher);
    }

    pub fn publish_batch(&mut self, logger_batch: LoggerBatch<S, E>) -> () {
        for pusher in (&mut self.event_pushers).iter_mut() {
            match logger_batch {
                LoggerBatch::Logs(evs) => {
                    if let Some(frontier) = self.frontier {
                        pusher.push(Event::Messages(frontier, evs.clone()));
                        let &(last_ts, _, _) = evs.last().unwrap();
                        let new_frontier = RootTimestamp::new(last_ts);
                        pusher.push(Event::Progress(vec![(new_frontier, 1), (frontier, -1)]));
                        self.frontier = Some(new_frontier);
                    }
                },
                LoggerBatch::End => {
                    if let Some(frontier) = self.frontier {
                        pusher.push(Event::Progress(vec![(frontier, -1)]));
                        self.frontier = None;
                    }
                },
            }
        }
    }
}
<commit_msg>construct an EventPusher per sender thread<commit_after>//! Traits, implementations, and macros related to logging timely events.

use std::io::Write;
use std::rc::Rc;
use std::sync::{Arc, Mutex};

use std::collections::HashMap;
use std::fmt::Debug;

use ::progress::timestamp::RootTimestamp;
use ::progress::nested::product::Product;

use dataflow::operators::capture::{EventWriter, Event, EventPusher};

use abomonation::Abomonation;

use std::net::TcpStream;

use timely_logging::BufferingLogger;
use timely_logging::Event as LogEvent;
use timely_logging::EventsSetup;
use timely_logging::{CommsEvent, CommsSetup};
use timely_logging::LoggerBatch;

type LogMessage = (u64, EventsSetup, LogEvent);
type CommsMessage = (u64, CommsSetup, CommsEvent);

/// TODO(andreal)
pub type Logger = Rc<BufferingLogger<EventsSetup, LogEvent>>;

/// TODO(andreal)
pub fn new_inactive_logger() -> Logger {
    BufferingLogger::<(), ()>::new_inactive()
}

type EventPusherFactory<M> = Arc<Fn()->Box<EventPusher<Product<RootTimestamp, u64>, M>+Send>+Send+Sync>;

/// Manages the logging channel subscriptions and log pushers.
pub struct LogManager {
    // Keeps track of the subscribers of timely log streams for each worker (whose index
    // is tracked by EventsSetup)
    timely_logs: HashMap<
        EventsSetup,
        Arc<Mutex<EventStreamSubscriptionManager<EventsSetup, LogEvent>>>>,
    // Keeps track of existing subscription requests to timely log streams. This lets us attach
    // subscribers to new log streams.
    timely_subscriptions:
        Vec<(Arc<Fn(&EventsSetup)->bool+Send+Sync>, EventPusherFactory<LogMessage>)>,
    // Keeps track of the subscribers of communication log streams for each comm thread
    // (whose identity is tracked by CommsSetup)
    communication_logs: HashMap<
        CommsSetup,
        Arc<Mutex<EventStreamSubscriptionManager<CommsSetup, CommsEvent>>>>,
    // Keeps track of existing subscription requests to communication log streams. This lets us attach
    // subscribers to new log streams.
    communication_subscriptions:
        Vec<(Arc<Fn(&CommsSetup)->bool+Send+Sync>, EventPusherFactory<CommsMessage>)>,
}

impl LogManager {
    fn add_timely_subscription(&mut self,
                               filter: Arc<Fn(&EventsSetup)->bool+Send+Sync>,
                               pusher: EventPusherFactory<LogMessage>) {

        for (_, ref event_manager) in self.timely_logs.iter().filter(|&(ref setup, _)| filter(setup)) {
            let this_pusher = pusher();
            this_pusher.push(Event::Progress(vec![(Default::default(), -1)]));
            event_manager.lock().unwrap().subscribe(this_pusher);
        }
        self.timely_subscriptions.push((filter, pusher));
    }

    fn add_communication_subscription(&mut self,
                                      filter: Arc<Fn(&CommsSetup)->bool+Send+Sync>,
                                      pusher: EventPusherFactory<CommsMessage>) {

        for (_, ref event_manager) in self.communication_logs.iter().filter(|&(ref setup, _)| filter(setup)) {
            let this_pusher = pusher();
            this_pusher.push(Event::Progress(vec![(Default::default(), -1)]));
            event_manager.lock().unwrap().subscribe(this_pusher);
        }
        self.communication_subscriptions.push((filter, pusher));
    }
}

struct SharedVec {
    inner: Arc<Mutex<Vec<u8>>>,
}

impl SharedVec {
    pub fn new(inner: Arc<Mutex<Vec<u8>>>) -> Self {
        SharedVec {
            inner: inner,
        }
    }
}

impl Write for SharedVec {
    fn write(&mut self, data: &[u8]) -> Result<usize, ::std::io::Error> {
        self.inner.lock().unwrap().extend_from_slice(data);
        Ok(data.len())
    }

    fn flush(&mut self) -> Result<(), ::std::io::Error> {
        Ok(())
    }
}

struct SharedEventWriter<T, D, W: Write> {
    inner: Mutex<EventWriter<T, D, W>>,
}

impl<T, D, W: Write> SharedEventWriter<T, D, W> {
    fn new(w: W) -> Self {
        SharedEventWriter {
            inner: Mutex::new(EventWriter::new(w)),
        }
    }
}

impl<T: Abomonation+Debug, D: Abomonation+Debug, W: Write> EventPusher<T, D> for SharedEventWriter<T, D, W> {
    fn push(&self, event: Event<T, D>) {
        let inner = self.inner.lock().expect("event pusher poisoned");
        inner.push(event)
    }
}

/// TODO(andreal)
pub struct FilteredLogManager<S, E> {
    log_manager: Arc<Mutex<LogManager>>,
    filter: Arc<Fn(&S)->bool+Send+Sync>,
    _e: ::std::marker::PhantomData<E>,
}

impl FilteredLogManager<EventsSetup, LogEvent> {
    /// TODO(andreal)
    pub fn to_tcp_socket(&mut self) {
        let target: String = ::std::env::var("TIMELY_LOG_TARGET").expect("no $TIMELY_LOG_TARGET, e.g. 127.0.0.1:34254");

        // let writer = SharedEventWriter::new(writer);
        let pusher: EventPusherFactory<LogMessage>= Arc::new(move || {
            Box::new(EventWriter::new(TcpStream::connect(target.clone()).expect("failed to connect to logging destination")))
        });

        self.log_manager.lock().unwrap().add_timely_subscription(self.filter.clone(), pusher);
    }

    // /// TODO(andreal)
    // pub fn to_bufs(&mut self) -> Vec<Arc<Mutex<Vec<u8>>>> {
    //     let mut vecs = Vec::new();

    //     for i in 0..4 {
    //         let buf = Arc::new(Mutex::new(Vec::<u8>::with_capacity(4_000_000_000)));
    //         let writer = SharedEventWriter::new(SharedVec::new(buf.clone()));
    //         let pusher: Arc<EventPusher<Product<RootTimestamp, u64>, LogMessage>+Send+Sync> = Arc::new(writer);
    //         self.log_manager.lock().unwrap().add_timely_subscription(Arc::new(move |s| s.index == i), pusher);
    //         vecs.push(buf);
    //     }

    //     vecs
    // }
}

impl FilteredLogManager<CommsSetup, CommsEvent> {
    /// TODO(andreal)
    pub fn to_tcp_socket(&mut self) {
        let comm_target = ::std::env::var("TIMELY_COMM_LOG_TARGET").expect("no $TIMELY_COMM_LOG_TARGET, e.g. 127.0.0.1:34255");

        let pusher: EventPusherFactory<CommsMessage> = Arc::new(move || {
            Box::new(EventWriter::new(TcpStream::connect(comm_target.clone()).expect("failed to connect to logging destination")))
        });

        self.log_manager.lock().unwrap().add_communication_subscription(self.filter.clone(), pusher);
    }
}

impl LogManager {
    /// TODO(andreal)
    pub fn new() -> Arc<Mutex<Self>> {
        Arc::new(Mutex::new(LogManager {
            timely_logs: HashMap::new(),
            timely_subscriptions: Vec::new(),
            communication_logs: HashMap::new(),
            communication_subscriptions: Vec::new(),
        }))
    }
}

/// TODO(andreal)
pub trait LogFilter {
    /// TODO(andreal)
    fn workers(&mut self) -> FilteredLogManager<EventsSetup, LogEvent>;

    /// TODO(andreal)
    fn comms(&mut self) -> FilteredLogManager<CommsSetup, CommsEvent>;
}

impl LogFilter for Arc<Mutex<LogManager>> {
    /// TODO(andreal)
    #[inline] fn workers(&mut self) -> FilteredLogManager<EventsSetup, LogEvent> {
        FilteredLogManager {
            log_manager: self.clone(),
            filter: Arc::new(|_| true),
            _e: ::std::marker::PhantomData,
        }
    }

    /// TODO(andreal)
    #[inline] fn comms(&mut self) -> FilteredLogManager<CommsSetup, CommsEvent> {
        FilteredLogManager {
            log_manager: self.clone(),
            filter: Arc::new(|_| true),
            _e: ::std::marker::PhantomData,
        }
    }
}

/// TODO(andreal)
pub struct LoggerConfig {
    /// TODO(andreal)
    pub timely_logging: Arc<Fn(EventsSetup)->Rc<BufferingLogger<EventsSetup, LogEvent>>+Send+Sync>,
    /// TODO(andreal)
    pub communication_logging: Arc<Fn(CommsSetup)->Rc<BufferingLogger<CommsSetup, CommsEvent>>+Send+Sync>,
}

impl LoggerConfig {
    fn register_timely_logger(
        log_manager: &mut LogManager,
        events_setup: EventsSetup) -> Arc<Mutex<EventStreamSubscriptionManager<EventsSetup, LogEvent>>> {

        let event_manager: Arc<Mutex<EventStreamSubscriptionManager<EventsSetup, LogEvent>>> = Arc::new(Mutex::new(Default::default()));
        log_manager.timely_logs.insert(events_setup, event_manager.clone());
        for pusher in log_manager.timely_subscriptions.iter().filter(|&&(ref f, _)| f(&events_setup)).map(|&(_, ref p)| p.clone()) {
            event_manager.lock().unwrap().subscribe(pusher());
        }
        println!("pushers: {}", event_manager.lock().unwrap().event_pushers.len());
        event_manager
    }

    fn register_comms_logger(
        log_manager: &mut LogManager,
        comms_setup: CommsSetup) -> Arc<Mutex<EventStreamSubscriptionManager<CommsSetup, CommsEvent>>> {

        let event_manager: Arc<Mutex<EventStreamSubscriptionManager<CommsSetup, CommsEvent>>> = Arc::new(Mutex::new(Default::default()));
        log_manager.communication_logs.insert(comms_setup, event_manager.clone());
        for pusher in log_manager.communication_subscriptions.iter().filter(|&&(ref f, _)| f(&comms_setup)).map(|&(_, ref p)| p.clone()) {
            event_manager.lock().unwrap().subscribe(pusher());
        }
        event_manager
    }

    /// TODO(andreal)
    pub fn new(log_manager: Arc<Mutex<LogManager>>) -> Self {
        let timely_logging_manager = log_manager.clone();
        let communication_logging_manager = log_manager;
        LoggerConfig {
            timely_logging: Arc::new(move |events_setup: EventsSetup| {
                let subscription_manager = LoggerConfig::register_timely_logger(
                    &mut timely_logging_manager.lock().unwrap(), events_setup);
                //eprintln!("registered timely logger: {:?}", events_setup);
                Rc::new(BufferingLogger::new(events_setup, Box::new(move |data| {
                    subscription_manager.lock().expect("cannot lock mutex").publish_batch(data);
                })))
            }),
            communication_logging: Arc::new(move |comms_setup: CommsSetup| {
                let subscription_manager = LoggerConfig::register_comms_logger(
                    &mut communication_logging_manager.lock().unwrap(), comms_setup);
                //eprintln!("registered comm logger: {:?}", comms_setup);
                Rc::new(BufferingLogger::new(comms_setup, Box::new(move |data| {
                    subscription_manager.lock().expect("cannot lock mutex").publish_batch(data);
                })))
            }),
        }
    }
}

impl Default for LoggerConfig {
    fn default() -> Self {
        LoggerConfig {
            timely_logging: Arc::new(|setup| Rc::new(BufferingLogger::new(setup, Box::new(|_| {})))),
            communication_logging: Arc::new(|setup| Rc::new(BufferingLogger::new(setup, Box::new(|_| {})))),
        }
    }
}

struct EventStreamSubscriptionManager<S, E> {
    // None when the logging stream is closed
    frontier: Option<Product<RootTimestamp, u64>>,
    event_pushers: Vec<Box<EventPusher<Product<RootTimestamp, u64>, (u64, S, E)>+Send>>,
}

impl<S, E> Default for EventStreamSubscriptionManager<S, E> {
    fn default() -> Self {
        EventStreamSubscriptionManager {
            frontier: Some(Default::default()),
            event_pushers: Vec::new(),
        }
    }
}

impl<S: Clone, E: Clone> EventStreamSubscriptionManager<S, E> {
    fn subscribe(&mut self, pusher: Box<EventPusher<Product<RootTimestamp, u64>, (u64, S, E)>+Send>) {
        if let Some(frontier) = self.frontier {
            // if this logging stream is open
            pusher.push(Event::Progress(vec![(frontier, 1)]));
        } else {
            eprintln!("logging: subscription to closed stream");
        }
        self.event_pushers.push(pusher);
    }

    pub fn publish_batch(&mut self, logger_batch: LoggerBatch<S, E>) -> () {
        for pusher in (&mut self.event_pushers).iter_mut() {
            match logger_batch {
                LoggerBatch::Logs(evs) => {
                    if let Some(frontier) = self.frontier {
                        pusher.push(Event::Messages(frontier, evs.clone()));
                        let &(last_ts, _, _) = evs.last().unwrap();
                        let new_frontier = RootTimestamp::new(last_ts);
                        pusher.push(Event::Progress(vec![(new_frontier, 1), (frontier, -1)]));
                        self.frontier = Some(new_frontier);
                    }
                },
                LoggerBatch::End => {
                    if let Some(frontier) = self.frontier {
                        pusher.push(Event::Progress(vec![(frontier, -1)]));
                        self.frontier = None;
                    }
                },
            }
        }
    }
}
<|endoftext|>