<commit_before>use ndarray::*;
use ndarray_linalg::*;

#[test]
fn fixed() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Upper).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fixed_t() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]).reversed_axes();
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Upper).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fixed_lower() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Lower).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fixed_t_lower() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]).reversed_axes();
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Lower).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn ssqrt() {
    let a: Array2<f64> = random_hpd(3);
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Upper).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}

#[test]
fn ssqrt_t() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Upper).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}

#[test]
fn ssqrt_lower() {
    let a: Array2<f64> = random_hpd(3);
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Lower).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}

#[test]
fn ssqrt_t_lower() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Lower).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}
<commit_msg>Add test for matching shape check in EighInplace<commit_after>use ndarray::*;
use ndarray_linalg::*;

#[should_panic]
#[test]
fn eigh_generalized_shape_mismatch() {
    let a = Array2::<f64>::eye(3);
    let b = Array2::<f64>::eye(2);
    let _ = (a, b).eigh_inplace(UPLO::Upper);
}

#[test]
fn fixed() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Upper).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fixed_t() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]).reversed_axes();
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Upper).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fixed_lower() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Lower).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn fixed_t_lower() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]).reversed_axes();
    let (e, vecs): (Array1<_>, Array2<_>) = (&a).eigh(UPLO::Lower).unwrap();
    assert_close_l2!(&e, &arr1(&[2.0, 2.0, 5.0]), 1.0e-7);

    // Check eigenvectors are orthogonalized
    let s = vecs.t().dot(&vecs);
    assert_close_l2!(&s, &Array::eye(3), 1.0e-7);

    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert_close_l2!(&av, &ev, 1.0e-7);
    }
}

#[test]
fn ssqrt() {
    let a: Array2<f64> = random_hpd(3);
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Upper).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}

#[test]
fn ssqrt_t() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Upper).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}

#[test]
fn ssqrt_lower() {
    let a: Array2<f64> = random_hpd(3);
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Lower).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}

#[test]
fn ssqrt_t_lower() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let ans = a.clone();
    let s = a.ssqrt(UPLO::Lower).unwrap();
    println!("a = {:?}", &ans);
    println!("s = {:?}", &s);
    assert_close_l2!(&s.t(), &s, 1e-7);
    let ss = s.dot(&s);
    println!("ss = {:?}", &ss);
    assert_close_l2!(&ss, &ans, 1e-7);
}
<|endoftext|>


<commit_before>use common::util::*;

extern crate uu_chown;
pub use self::uu_chown::*;

static UTIL_NAME: &'static str = "chown";

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

    #[test]
    fn test_getuid() {
        assert_eq!(0, getuid("root").unwrap());
        assert!(getuid("88888888").is_err());
        assert!(getuid("agroupthatdoesntexist").is_err());
    }

    #[test]
    fn test_getgid() {
        assert_eq!(0, getgid("root").unwrap());
        assert!(getgid("88888888").is_err());
        assert!(getgid("agroupthatdoesntexist").is_err());
    }

    #[test]
    fn test_uid2usr() {
        assert_eq!("root", uid2usr(0).unwrap());
        assert!(uid2usr(88888888).is_err());
    }

    #[test]
    fn test_gid2grp() {
        assert_eq!("root", gid2grp(0).unwrap());
        assert!(gid2grp(88888888).is_err());
    }
}

#[test]
fn test_invalid_option() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    ucmd.arg("-w").arg("-q").arg("/");
    ucmd.fails();
}
<commit_msg>chown: Fix error on mac<commit_after>use common::util::*;

extern crate uu_chown;
pub use self::uu_chown::*;

static UTIL_NAME: &'static str = "chown";

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

    #[test]
    fn test_getuid() {
        assert_eq!(0, getuid("root").unwrap());
        assert!(getuid("88888888").is_err());
        assert!(getuid("auserthatdoesntexist").is_err());
    }

    #[test]
    fn test_getgid() {
        if cfg!(target_os = "macos") {
            assert_eq!(0, getgid("wheel").unwrap());
        } else {
            assert_eq!(0, getgid("root").unwrap());
        }
        assert!(getgid("88888888").is_err());
        assert!(getgid("agroupthatdoesntexist").is_err());
    }

    #[test]
    fn test_uid2usr() {
        assert_eq!("root", uid2usr(0).unwrap());
        assert!(uid2usr(88888888).is_err());
    }

    #[test]
    fn test_gid2grp() {
        if cfg!(target_os = "macos") {
            assert_eq!("wheel", gid2grp(0).unwrap());
        } else {
            assert_eq!("root", gid2grp(0).unwrap());
        }
        assert!(gid2grp(88888888).is_err());
    }
}

#[test]
fn test_invalid_option() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    ucmd.arg("-w").arg("-q").arg("/");
    ucmd.fails();
}
<|endoftext|>


<commit_before>//
// Copyright 2022 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Trusted Shuffler implementation.

#[cfg(test)]
mod tests;

use anyhow::{anyhow, Context};
use async_trait::async_trait;
use futures::{stream::FuturesOrdered, StreamExt};
use hyper::Uri;
use std::{
    cmp::Ordering,
    mem::take,
    ops::DerefMut,
    sync::{Arc, Mutex},
    vec,
};
use tokio::{sync::oneshot, time::Duration};

#[derive(Debug, PartialEq)]
pub struct TrustedShufflerRequest {
    pub body: Vec<u8>,
    pub uri: Uri,
}
#[derive(Debug, PartialEq)]
pub struct TrustedShufflerResponse {
    pub body: Vec<u8>,
}

impl TrustedShufflerResponse {
    fn empty() -> TrustedShufflerResponse {
        TrustedShufflerResponse { body: vec![] }
    }
}

// Workaround so we can have either a request or a response in `data` of `Message`.
// We should be able to refactor so we do not need the `Wrapper` (and `panics`) any more.
#[derive(Debug)]
enum Wrapper {
    Request(TrustedShufflerRequest),
    Response(TrustedShufflerResponse),
}

// We only compare the body, but we need revisit this and decide if this
// is how we want to sort our requests and responses.
fn cmp(w1: &Wrapper, w2: &Wrapper) -> Ordering {
    match (w1, w2) {
        (Wrapper::Request(r1), Wrapper::Request(r2)) => r1.body.cmp(&r2.body),
        (Wrapper::Response(r1), Wrapper::Response(r2)) => r1.body.cmp(&r2.body),
        (_, _) => panic!(
            "Fail to compare a TrustedShufflerRequest: {:?} and a TrustedShufflerResponse: {:?}",
            w1, w2
        ),
    }
}

struct Message {
    // Determines the original order in which messages arrived.
    // Index is used to send requests back to the client in the order of arrival.
    index: usize,
    // Arbitrary message data.
    data: Wrapper,
    // Channel for sending responses back to the client async tasks.
    response_sender: oneshot::Sender<TrustedShufflerResponse>,
}

#[async_trait]
pub trait RequestHandler: Send + Sync {
    async fn handle(
        &self,
        request: TrustedShufflerRequest,
    ) -> anyhow::Result<TrustedShufflerResponse>;
}

// Trusted Shuffler implementation.
pub struct TrustedShuffler {
    // Value k that represents k-anonymity.
    k: usize,

    // When the k-th request in a batch arrives we start a timeout. For any request were the
    // Trusted Shuffler did not receive a response from the backend after the timeout, the Trusted
    // Shuffler sends an empty response.
    timeout: Option<Duration>,

    // Current batch of requests to be shuffled.
    // Mutex is used because messages are collected in different async tasks.
    requests_to_shuffle: Arc<Mutex<Vec<Message>>>,

    // Async function that sends a request to the backend and returns a response.
    request_handler: Arc<dyn RequestHandler>,
}

impl TrustedShuffler {
    pub fn new(
        k: usize,
        timeout: Option<Duration>,
        request_handler: Arc<dyn RequestHandler>,
    ) -> Self {
        Self {
            k,
            timeout,
            requests_to_shuffle: Arc::new(Mutex::new(vec![])),
            request_handler,
        }
    }

    // Asynchronously handles an incoming request.
    pub async fn invoke(
        &self,
        request: TrustedShufflerRequest,
    ) -> anyhow::Result<TrustedShufflerResponse> {
        let (response_sender, response_receiver) = oneshot::channel();

        // Check if the request batch is filled and create a separate task for shuffling requests.
        {
            let mut requests_to_shuffle = self
                .requests_to_shuffle
                .lock()
                .map_err(|error| anyhow!("Couldn't lock current messages mutex: {:?}", error))?;

            let request = Message {
                index: requests_to_shuffle.len(),
                data: Wrapper::Request(request),
                response_sender,
            };

            requests_to_shuffle.push(request);

            if requests_to_shuffle.len() >= self.k {
                // Replace current requests with an empty vector.
                let requests = take(requests_to_shuffle.deref_mut());

                // Shuffle requests and spawn async tasks for sending them to the backend.
                let request_handler = self.request_handler.clone();
                let timeout = self.timeout;
                tokio::spawn(async move {
                    if let Err(error) =
                        TrustedShuffler::shuffle_requests(requests, request_handler, timeout).await
                    {
                        log::error!("Shuffling error: {:?}", error);
                    }
                });
            }
        }

        response_receiver.await.context("Couldn't receive response")
    }

    // Lexicographically sorts requests and sends them to the backend using the
    // [`TrustedShuffler::request_handler`]. For every batch of requests it either waits until all
    // responses are received, except if a timeout is set, then it sends a default response.
    async fn shuffle_requests(
        mut requests: Vec<Message>,
        request_handler: Arc<dyn RequestHandler>,
        timeout: Option<Duration>,
    ) -> anyhow::Result<()> {
        requests.sort_by(|first, second| cmp(&first.data, &second.data));

        let response_futures: FuturesOrdered<_> = requests
            .into_iter()
            .map(|request_message| {
                // Deconstruct the Message holding a request in data.
                let request_handler_clone = request_handler.clone();
                let index = request_message.index;
                let response_sender = request_message.response_sender;
                let data = get_request(request_message.data);
                async move {
                    let response = match timeout {
                        None => request_handler_clone.handle(data).await,
                        Some(timeout) => {
                            match tokio::time::timeout(timeout, request_handler_clone.handle(data))
                                .await
                            {
                                Err(_) => Ok(TrustedShufflerResponse::empty()),
                                Ok(response) => response,
                            }
                        }
                    };
                    // Create a Message holding the response in data.
                    response.map(|response| Message {
                        index,
                        data: Wrapper::Response(response),
                        response_sender,
                    })
                }
            })
            .collect();
        let responses = response_futures
            .collect::<Vec<Result<_, _>>>()
            .await
            .into_iter()
            .collect::<Result<Vec<_>, _>>()
            .context("Couldn't send responses")?;

        Self::shuffle_responses(responses)
    }

    // Restores the original order in which messages arrived and sends them back to the client async
    // tasks using corresponding channels defined in the [`Message::response_sender`].
    fn shuffle_responses(mut responses: Vec<Message>) -> anyhow::Result<()> {
        responses.sort_by_key(|response| response.index);

        responses
            .into_iter()
            .map(
                |Message {
                     index: _,
                     data,
                     response_sender,
                 }| {
                    response_sender
                        .send(get_response(data))
                        .map_err(|_data| anyhow!("Couldn't send response"))
                },
            )
            .collect::<Result<Vec<_>, _>>()
            .map(|_: Vec<()>| ())
    }
}

fn get_request(w: Wrapper) -> TrustedShufflerRequest {
    match w {
        Wrapper::Request(r) => r,
        _ => panic!(
            "Expected a TrustedShufflerRequest, but found a TrustedShufflerResponse: {:?}",
            w
        ),
    }
}

fn get_response(w: Wrapper) -> TrustedShufflerResponse {
    match w {
        Wrapper::Response(r) => r,
        _ => panic!(
            "Expected a TrustedShufflerResponse, but found a TrustedShufflerRequest: {:?}",
            w
        ),
    }
}
<commit_msg>Remove Wrapper by splitting to Request/ResponseMessage (#3101)<commit_after>//
// Copyright 2022 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Trusted Shuffler implementation.

#[cfg(test)]
mod tests;

use anyhow::{anyhow, Context};
use async_trait::async_trait;
use futures::{stream::FuturesOrdered, StreamExt};
use hyper::Uri;
use std::{
    cmp::Ordering,
    mem::take,
    ops::DerefMut,
    sync::{Arc, Mutex},
    vec,
};
use tokio::{sync::oneshot, time::Duration};

#[derive(Debug, PartialEq)]
pub struct TrustedShufflerRequest {
    pub body: Vec<u8>,
    pub uri: Uri,
}

impl TrustedShufflerRequest {
    // We only compare the body, and we need revisit this and decide if this
    // is how we want to sort our requests.
    fn compare_body(&self, r2: &TrustedShufflerRequest) -> Ordering {
        self.body.cmp(&r2.body)
    }
}

#[derive(Debug, PartialEq)]
pub struct TrustedShufflerResponse {
    pub body: Vec<u8>,
}

impl TrustedShufflerResponse {
    fn empty() -> TrustedShufflerResponse {
        TrustedShufflerResponse { body: vec![] }
    }
}

struct RequestMessage {
    // Determines the original order in which Trusted Shuffler Requests arrived.
    // Index is used to send responses back to the client in the order of arrival.
    index: usize,
    // A TrustedShufflerRequest.
    data: TrustedShufflerRequest,
    // Channel for sending responses back to the client async tasks.
    response_sender: oneshot::Sender<TrustedShufflerResponse>,
}

struct ResponseMessage {
    // Copied from the corresponding RequestMessage.
    // Determines the original order in which the Trusted Shuffler Request for the Response
    // arrived. Index is used to send responses back to the client in the order of arrival.
    index: usize,
    // The TrustedShufflerResponse to a TrustedShufflerRequest.
    data: TrustedShufflerResponse,
    // Copied from the corresponding RequestMessage.
    // Channel for sending responses back to the client async tasks.
    response_sender: oneshot::Sender<TrustedShufflerResponse>,
}

#[async_trait]
pub trait RequestHandler: Send + Sync {
    async fn handle(
        &self,
        request: TrustedShufflerRequest,
    ) -> anyhow::Result<TrustedShufflerResponse>;
}

// Trusted Shuffler implementation.
pub struct TrustedShuffler {
    // Value k that represents k-anonymity.
    k: usize,

    // When the k-th request in a batch arrives we start a timeout. For any request were the
    // Trusted Shuffler did not receive a response from the backend after the timeout, the Trusted
    // Shuffler sends an empty response.
    timeout: Option<Duration>,

    // Current batch of requests to be shuffled.
    // Mutex is used because messages are collected in different async tasks.
    requests_to_shuffle: Arc<Mutex<Vec<RequestMessage>>>,

    // Async function that sends a request to the backend and returns a response.
    request_handler: Arc<dyn RequestHandler>,
}

impl TrustedShuffler {
    pub fn new(
        k: usize,
        timeout: Option<Duration>,
        request_handler: Arc<dyn RequestHandler>,
    ) -> Self {
        Self {
            k,
            timeout,
            requests_to_shuffle: Arc::new(Mutex::new(vec![])),
            request_handler,
        }
    }

    // Asynchronously handles an incoming request.
    pub async fn invoke(
        &self,
        request: TrustedShufflerRequest,
    ) -> anyhow::Result<TrustedShufflerResponse> {
        let (response_sender, response_receiver) = oneshot::channel();

        // Check if the request batch is filled and create a separate task for shuffling requests.
        {
            let mut requests_to_shuffle = self
                .requests_to_shuffle
                .lock()
                .map_err(|error| anyhow!("Couldn't lock current messages mutex: {:?}", error))?;

            let request = RequestMessage {
                index: requests_to_shuffle.len(),
                data: request,
                response_sender,
            };

            requests_to_shuffle.push(request);

            if requests_to_shuffle.len() >= self.k {
                // Replace current requests with an empty vector.
                let requests = take(requests_to_shuffle.deref_mut());

                // Shuffle requests and spawn async tasks for sending them to the backend.
                let request_handler = self.request_handler.clone();
                let timeout = self.timeout;
                tokio::spawn(async move {
                    if let Err(error) =
                        TrustedShuffler::shuffle_requests(requests, request_handler, timeout).await
                    {
                        log::error!("Shuffling error: {:?}", error);
                    }
                });
            }
        }

        response_receiver.await.context("Couldn't receive response")
    }

    // Lexicographically sorts requests and sends them to the backend using the
    // [`TrustedShuffler::request_handler`]. For every batch of requests it either waits until all
    // responses are received, except if a timeout is set, then it sends a default response.
    async fn shuffle_requests(
        mut requests: Vec<RequestMessage>,
        request_handler: Arc<dyn RequestHandler>,
        timeout: Option<Duration>,
    ) -> anyhow::Result<()> {
        requests.sort_by(|first, second| first.data.compare_body(&second.data));

        let response_futures: FuturesOrdered<_> = requests
            .into_iter()
            .map(|request_message| {
                // Deconstruct the Message holding a request in data.
                let request_handler_clone = request_handler.clone();
                let index = request_message.index;
                let response_sender = request_message.response_sender;
                let data = request_message.data;
                async move {
                    let response = match timeout {
                        None => request_handler_clone.handle(data).await,
                        Some(timeout) => {
                            match tokio::time::timeout(timeout, request_handler_clone.handle(data))
                                .await
                            {
                                Err(_) => Ok(TrustedShufflerResponse::empty()),
                                Ok(response) => response,
                            }
                        }
                    };
                    // Create a Message holding the response in data.
                    response.map(|response| ResponseMessage {
                        index,
                        data: response,
                        response_sender,
                    })
                }
            })
            .collect();
        let responses = response_futures
            .collect::<Vec<Result<_, _>>>()
            .await
            .into_iter()
            .collect::<Result<Vec<_>, _>>()
            .context("Couldn't send responses")?;

        Self::shuffle_responses(responses)
    }

    // Restores the original order in which messages arrived and sends them back to the client async
    // tasks using corresponding channels defined in the [`Message::response_sender`].
    fn shuffle_responses(mut responses: Vec<ResponseMessage>) -> anyhow::Result<()> {
        responses.sort_by_key(|response| response.index);

        responses
            .into_iter()
            .map(
                |ResponseMessage {
                     index: _,
                     data,
                     response_sender,
                 }| {
                    response_sender
                        .send(data)
                        .map_err(|_data| anyhow!("Couldn't send response"))
                },
            )
            .collect::<Result<Vec<_>, _>>()
            .map(|_: Vec<()>| ())
    }
}
<|endoftext|>


<commit_before>//! A crate for analyzing the contents of the [rust-rosetta] repository.
//!
//! [rust-rosetta]: https://github.com/Hoverbear/rust-rosetta

#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate url;

extern crate regex;
extern crate reqwest;
extern crate toml;
extern crate walkdir;

extern crate find_unimplemented_tasks;

// Used by the test_sort macro.
#[doc(hidden)]
pub extern crate rand;

use std::collections::{HashSet, VecDeque};
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::iter::FromIterator;
use std::ops::Sub;

use regex::Regex;
use url::Url;

pub mod local;
pub mod remote;

#[macro_use]
pub mod test_utils;

use local::LocalTask;
use remote::RemoteTask;

lazy_static! {
    /// A Regex that matches valid RosettaCode URLs.
    static ref TASK_URL_RE: Regex =
        Regex::new(r"^http://rosettacode\.org/wiki/([^#]+)$").unwrap();
}

/// A representation of a RosettaCode task. Contains information about the implementation on both
/// the local repository and the wiki.
#[derive(Debug, Clone)]
pub struct Task {
    local: Option<LocalTask>,
    remote: RemoteTask,
}

impl Task {
    /// Returns the title of the task.
    pub fn title(&self) -> String {
        self.remote.title()
    }

    /// Returns the implementation of the task in the local repository, if it exists.
    pub fn local_code(&self) -> Option<String> {
        self.local.clone().map(|task| {
            // FIXME: Too simple for the multiple source file case.
            let mut code = String::new();

            for source in &task.source() {
                let mut file = File::open(source).unwrap();
                file.read_to_string(&mut code).unwrap();
            }

            code
        })
    }

    /// Returns the implementation of the task on the wiki, if it exists.
    pub fn remote_code(&self) -> Option<String> {
        self.remote.source()
    }

    /// True if and only if the task is only implemented on the Rosetta Code wiki.
    pub fn is_remote_only(&self) -> bool {
        self.local.is_none() && self.remote.source().is_some()
    }

    /// True if and only if the task is is only implemented in the repository.
    pub fn is_local_only(&self) -> bool {
        self.local.is_some() && self.remote.source().is_none()
    }

    /// True if and only if the task is neither implemented on the Rosetta Code wiki or on the
    /// repository.
    pub fn is_unimplemented(&self) -> bool {
        self.local.is_none() && self.remote.source().is_none()
    }

    /// Returns the URL of the task on the Rosetta Code wiki.
    pub fn url(&self) -> Url {
        self.remote.url()
    }
}

/// An iterator over tasks. Parses information from both the rust-rosetta repository and the
/// RosettaCode wiki.
pub struct TaskIterator {
    requested_task_titles: VecDeque<String>,
    local_tasks: Vec<LocalTask>,
}

impl TaskIterator {
    /// Creates a new iterator over the specified tasks. If no tasks are supplied, iterates over
    /// all tasks.
    pub fn new<P>(workspace_root: P, titles: &[String]) -> TaskIterator
        where P: AsRef<Path>
    {
        let local_tasks = local::parse_tasks(workspace_root.as_ref().join("Cargo.toml"));

        let all_task_titles = remote::all_task_titles().into_iter().collect::<HashSet<_>>();

        let all_decoded_task_titles = all_task_titles.iter()
            .map(|title| remote::decode_title(title))
            .collect::<HashSet<_>>();

        let all_local_task_titles =
            local_tasks.iter().map(|task| task.title()).collect::<HashSet<_>>();

        if !all_local_task_titles.is_subset(&all_decoded_task_titles) {
            // If there are tasks that can't be matched on the wiki, it's possible that they are
            // just draft tasks at the moment. Check them by seeing if the server response with
            // 404.
            let possible_bad_local_titles = all_local_task_titles.sub(&all_decoded_task_titles);

            let mut bad_titles = vec![];
            for title in &possible_bad_local_titles {
                let task_result = remote::request_task(title);

                if task_result.is_err() {
                    bad_titles.push(title);
                }
            }

            if !bad_titles.is_empty() {
                panic!("Could not match some local tasks to tasks on the wiki: {:?}",
                       bad_titles);
            }
        }

        let mut requested_task_titles: Vec<_> = if titles.is_empty() {
            all_task_titles.into_iter().collect()
        } else {
            all_task_titles.intersection(&HashSet::from_iter(titles.iter().cloned()))
                .cloned()
                .collect()
        };

        requested_task_titles.sort();

        TaskIterator {
            requested_task_titles: requested_task_titles.into_iter().collect(),
            local_tasks: local_tasks,
        }
    }
}

impl Iterator for TaskIterator {
    type Item = Task;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(ref title) = self.requested_task_titles.pop_front() {
            let local_task = self.local_tasks
                .iter()
                .cloned()
                .find(|task| task.title() == title.as_str());
            let remote_task = remote::request_task(&title).unwrap();

            let task = Task {
                local: local_task.clone(),
                remote: remote_task.clone(),
            };

            Some(task)
        } else {
            None
        }
    }
}

/// Retrieves data for every task on Rosetta Code.
pub fn fetch_all_tasks<P>(workspace_root: P) -> TaskIterator
    where P: AsRef<Path>
{
    TaskIterator::new(workspace_root, &vec![])
}

/// Parses both local (implemented in this repository) and remote (implemented on the wiki) tasks,
/// and returns the code of each.
pub fn fetch_tasks<P>(workspace_root: P, tasks: &[String]) -> TaskIterator
    where P: AsRef<Path>
{
    TaskIterator::new(workspace_root, &tasks)
}
<commit_msg>print error on wiki request error<commit_after>//! A crate for analyzing the contents of the [rust-rosetta] repository.
//!
//! [rust-rosetta]: https://github.com/Hoverbear/rust-rosetta

#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate url;

extern crate regex;
extern crate reqwest;
extern crate toml;
extern crate walkdir;

extern crate find_unimplemented_tasks;

// Used by the test_sort macro.
#[doc(hidden)]
pub extern crate rand;

use std::collections::{HashSet, VecDeque};
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::iter::FromIterator;
use std::ops::Sub;
use std::path::Path;
use std::process;

use regex::Regex;
use url::Url;

pub mod local;
pub mod remote;

#[macro_use]
pub mod test_utils;

use local::LocalTask;
use remote::RemoteTask;

lazy_static! {
    /// A Regex that matches valid RosettaCode URLs.
    static ref TASK_URL_RE: Regex =
        Regex::new(r"^http://rosettacode\.org/wiki/([^#]+)$").unwrap();
}

/// A representation of a RosettaCode task. Contains information about the implementation on both
/// the local repository and the wiki.
#[derive(Debug, Clone)]
pub struct Task {
    local: Option<LocalTask>,
    remote: RemoteTask,
}

impl Task {
    /// Returns the title of the task.
    pub fn title(&self) -> String {
        self.remote.title()
    }

    /// Returns the implementation of the task in the local repository, if it exists.
    pub fn local_code(&self) -> Option<String> {
        self.local.clone().map(|task| {
            // FIXME: Too simple for the multiple source file case.
            let mut code = String::new();

            for source in &task.source() {
                let mut file = File::open(source).unwrap();
                file.read_to_string(&mut code).unwrap();
            }

            code
        })
    }

    /// Returns the implementation of the task on the wiki, if it exists.
    pub fn remote_code(&self) -> Option<String> {
        self.remote.source()
    }

    /// True if and only if the task is only implemented on the Rosetta Code wiki.
    pub fn is_remote_only(&self) -> bool {
        self.local.is_none() && self.remote.source().is_some()
    }

    /// True if and only if the task is is only implemented in the repository.
    pub fn is_local_only(&self) -> bool {
        self.local.is_some() && self.remote.source().is_none()
    }

    /// True if and only if the task is neither implemented on the Rosetta Code wiki or on the
    /// repository.
    pub fn is_unimplemented(&self) -> bool {
        self.local.is_none() && self.remote.source().is_none()
    }

    /// Returns the URL of the task on the Rosetta Code wiki.
    pub fn url(&self) -> Url {
        self.remote.url()
    }
}

/// An iterator over tasks. Parses information from both the rust-rosetta repository and the
/// RosettaCode wiki.
pub struct TaskIterator {
    requested_task_titles: VecDeque<String>,
    local_tasks: Vec<LocalTask>,
}

impl TaskIterator {
    /// Creates a new iterator over the specified tasks. If no tasks are supplied, iterates over
    /// all tasks.
    pub fn new<P>(workspace_root: P, titles: &[String]) -> TaskIterator
        where P: AsRef<Path>
    {
        let local_tasks = local::parse_tasks(workspace_root.as_ref().join("Cargo.toml"));

        let all_task_titles = remote::all_task_titles().into_iter().collect::<HashSet<_>>();

        let all_decoded_task_titles = all_task_titles.iter()
            .map(|title| remote::decode_title(title))
            .collect::<HashSet<_>>();

        let all_local_task_titles =
            local_tasks.iter().map(|task| task.title()).collect::<HashSet<_>>();

        if !all_local_task_titles.is_subset(&all_decoded_task_titles) {
            // If there are tasks that can't be matched on the wiki, it's possible that they are
            // just draft tasks at the moment. Check them by seeing if the server response with
            // 404.
            let possible_bad_local_titles = all_local_task_titles.sub(&all_decoded_task_titles);

            let mut bad_titles = vec![];
            for title in &possible_bad_local_titles {
                let task_result = remote::request_task(title);

                if task_result.is_err() {
                    bad_titles.push(title);
                }
            }

            if !bad_titles.is_empty() {
                panic!("Could not match some local tasks to tasks on the wiki: {:?}",
                       bad_titles);
            }
        }

        let mut requested_task_titles: Vec<_> = if titles.is_empty() {
            all_task_titles.into_iter().collect()
        } else {
            all_task_titles.intersection(&HashSet::from_iter(titles.iter().cloned()))
                .cloned()
                .collect()
        };

        requested_task_titles.sort();

        TaskIterator {
            requested_task_titles: requested_task_titles.into_iter().collect(),
            local_tasks: local_tasks,
        }
    }
}

impl Iterator for TaskIterator {
    type Item = Task;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(ref title) = self.requested_task_titles.pop_front() {
            let local_task = self.local_tasks
                .iter()
                .cloned()
                .find(|task| task.title() == title.as_str());
            let remote_task = match remote::request_task(&title) {
                Ok(remote_task) => remote_task,
                Err(e) => {
                    writeln!(io::stderr(), "Error while requesting task: {}", e).unwrap();
                    process::exit(1);
                }
            };

            let task = Task {
                local: local_task.clone(),
                remote: remote_task.clone(),
            };

            Some(task)
        } else {
            None
        }
    }
}

/// Retrieves data for every task on Rosetta Code.
pub fn fetch_all_tasks<P>(workspace_root: P) -> TaskIterator
    where P: AsRef<Path>
{
    TaskIterator::new(workspace_root, &vec![])
}

/// Parses both local (implemented in this repository) and remote (implemented on the wiki) tasks,
/// and returns the code of each.
pub fn fetch_tasks<P>(workspace_root: P, tasks: &[String]) -> TaskIterator
    where P: AsRef<Path>
{
    TaskIterator::new(workspace_root, &tasks)
}
<|endoftext|>


<commit_before>extern crate fuse;
extern crate libc;
extern crate time;
extern crate argparse;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::string::String;
use std::fmt;
use std::env;
use std::path::Path;
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;

use log::LogLevel::Debug;

use libc::{ENOSYS,c_int,ENOENT};
use time::Timespec;
use argparse::{ArgumentParser, StoreTrue, Store};
use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyEmpty, ReplyDirectory};

// FIXME these are ugly as fuck and it seems like a BAD DECISION to have these kind of macros in rust.
// FIXME in any case, clean up our usage of these later.
// from: http://stackoverflow.com/questions/28392008/more-concise-hashmap-initialization
// auto-converts to String
macro_rules! hashmap {
    ($( $key: expr => $val: expr ),*) => {{
         let mut map = ::std::collections::HashMap::new();
         $( map.insert($key.to_string(), $val); )*
         map
    }}
}
// similar to above, jesus christ this is terrible
macro_rules! hashset {
    ($( $x: expr ),* ) => {{
            let mut set = HashSet::new();
            $( set.insert($x.to_string()); )*
            set
    }}
}

const TTL: Timespec = Timespec { sec: 1, nsec: 0 };                 // 1 second

const CREATE_TIME: Timespec = Timespec { sec: 1381237736, nsec: 0 };    // 2013-10-08 08:56

const HELLO_DIR_ATTR: FileAttr = FileAttr {
    ino: 1,
    size: 0,
    blocks: 0,
    atime: CREATE_TIME,
    mtime: CREATE_TIME,
    ctime: CREATE_TIME,
    crtime: CREATE_TIME,
    kind: FileType::Directory,
    perm: 0o755,
    nlink: 2,
    uid: 501,
    gid: 20,
    rdev: 0,
    flags: 0,
};

const HELLO_TXT_CONTENT: &'static str = "Hello World!\n";

const HELLO_TXT_ATTR: FileAttr = FileAttr {
    ino: 2,
    size: 13,
    blocks: 1,
    atime: CREATE_TIME,
    mtime: CREATE_TIME,
    ctime: CREATE_TIME,
    crtime: CREATE_TIME,
    kind: FileType::RegularFile,
    perm: 0o644,
    nlink: 1,
    uid: 501,
    gid: 20,
    rdev: 0,
    flags: 0,
};

struct UrchinFSEntry {
    display_name: String,
    destination: String,
    metadata: HashMap<String, HashSet<String>>
}

struct UrchinFS {
    entries: Vec<UrchinFSEntry>
}

impl Filesystem for UrchinFS {
    fn lookup (&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        info!("lookup parent:{} name:{}", parent, name.to_str().unwrap());
        if parent == 1 && name.to_str() == Some("hello.txt") {
            reply.entry(&TTL, &HELLO_TXT_ATTR, 0);
        } else {
            reply.error(ENOENT);
        }
    }

    fn getattr (&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        info!("getattr {}", ino);
        match ino {
            1 => reply.attr(&TTL, &HELLO_DIR_ATTR),
            2 => reply.attr(&TTL, &HELLO_TXT_ATTR),
            _ => reply.error(ENOENT),
        }
    }

    fn read (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, _size: u32, reply: ReplyData) {
        info!("read ino:{} offset:{}", ino, offset);
        if ino == 2 {
            reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]);
        } else {
            reply.error(ENOENT);
        }
    }

    fn readdir (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, mut reply: ReplyDirectory) {
        info!("readdir ino:{} offset:{}", ino, offset);
        if ino == 1 {
            if offset == 0 {
                reply.add(1, 0, FileType::Directory, ".");
                reply.add(1, 1, FileType::Directory, "..");
                reply.add(2, 2, FileType::RegularFile, "hello.txt");
            }
            reply.ok();
        } else {
            reply.error(ENOENT);
        }
    }

    fn access (&mut self, _req: &Request, ino: u64, _mask: u32, reply: ReplyEmpty) {
        info!("access ino:{}", ino);
        reply.error(ENOSYS);
    }
}

fn main () {
    env_logger::init().unwrap();

    let mut mountpoint = String::new();
    let mut optstr = String::new();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("faceted-search FUSE filesystem");
        ap.refer(&mut optstr).add_option(&["-o", "--options"], Store, "comma-separated mount options");
        ap.refer(&mut mountpoint).add_argument("mountpoint", Store, "the mountpoint").required();
        ap.parse_args_or_exit();
    }

// -o plugin=foo,plugin=bar,source=/home/kellen/films/,glob=*.json,format=json,watch=true,type=directory,formatter=generic
// FIXME dynamically load plugins for globbing/formatting see:
// http://stackoverflow.com/questions/22461457/does-rust-have-a-dlopen-equivalent

    // FIXME seems weird to have to have two variable refs
    let vec;
    let mut options : &[&OsStr] = &[];
    if optstr.trim() != "" {
        vec = optstr.trim().split(",").map(|s| OsStr::new(s)).collect::<Vec<_>>();
        options = &vec;
    }

    if log_enabled!(Debug) {
        if options.len() > 0 {
            debug!("using options:");
            for s in options {
                match s.to_str() {
                    Some(y) => {debug!("\t{}", y);}
                    None => {}
                }
            }
        }
    }

    // FIMXE do this better
    let easter = UrchinFSEntry {
        display_name: "Easter Parade (1948, color)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1948"], "color" => hashset!["color"]]
    };
    let city = UrchinFSEntry {
        display_name: "The Naked City (1948, bw)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1948"], "color" => hashset!["black-and-white"]]
    };
    let vanish = UrchinFSEntry {
        display_name: "The Lady Vanishes (1938, bw)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1938"], "color" => hashset!["black-and-white"]]
    };
    let kiss = UrchinFSEntry {
        display_name: "Kiss Me Deadly (1955, bw)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1955"], "color" => hashset!["black-and-white"]]
    };

    fuse::mount(UrchinFS {entries: vec![easter, city, vanish, kiss]}, &mountpoint, options);
}
<commit_msg>non-working attempt to find the path<commit_after>extern crate fuse;
extern crate libc;
extern crate time;
extern crate argparse;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::string::String;
use std::fmt;
use std::env;
use std::path::Path;
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;

use log::LogLevel::Debug;

use libc::{ENOSYS,c_int,ENOENT};
use time::Timespec;
use argparse::{ArgumentParser, StoreTrue, Store};
use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyEmpty, ReplyDirectory};
use fuse::argument::ArgumentIterator;

// FIXME these are ugly as fuck and it seems like a BAD DECISION to have these kind of macros in rust.
// FIXME in any case, clean up our usage of these later.
// from: http://stackoverflow.com/questions/28392008/more-concise-hashmap-initialization
// auto-converts to String
macro_rules! hashmap {
    ($( $key: expr => $val: expr ),*) => {{
         let mut map = ::std::collections::HashMap::new();
         $( map.insert($key.to_string(), $val); )*
         map
    }}
}
// similar to above, jesus christ this is terrible
macro_rules! hashset {
    ($( $x: expr ),* ) => {{
            let mut set = HashSet::new();
            $( set.insert($x.to_string()); )*
            set
    }}
}

const TTL: Timespec = Timespec { sec: 1, nsec: 0 };                 // 1 second

const CREATE_TIME: Timespec = Timespec { sec: 1381237736, nsec: 0 };    // 2013-10-08 08:56

const HELLO_DIR_ATTR: FileAttr = FileAttr {
    ino: 1,
    size: 0,
    blocks: 0,
    atime: CREATE_TIME,
    mtime: CREATE_TIME,
    ctime: CREATE_TIME,
    crtime: CREATE_TIME,
    kind: FileType::Directory,
    perm: 0o755,
    nlink: 2,
    uid: 501,
    gid: 20,
    rdev: 0,
    flags: 0,
};

const HELLO_TXT_CONTENT: &'static str = "Hello World!\n";

const HELLO_TXT_ATTR: FileAttr = FileAttr {
    ino: 2,
    size: 13,
    blocks: 1,
    atime: CREATE_TIME,
    mtime: CREATE_TIME,
    ctime: CREATE_TIME,
    crtime: CREATE_TIME,
    kind: FileType::RegularFile,
    perm: 0o644,
    nlink: 1,
    uid: 501,
    gid: 20,
    rdev: 0,
    flags: 0,
};

struct UrchinFSEntry {
    display_name: String,
    destination: String,
    metadata: HashMap<String, HashSet<String>>
}

struct UrchinFS {
    entries: Vec<UrchinFSEntry>
}

impl Filesystem for UrchinFS {
    fn lookup (&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        info!("lookup parent:{} name:{}", parent, name.to_str().unwrap());
        if parent == 1 && name.to_str() == Some("hello.txt") {
            reply.entry(&TTL, &HELLO_TXT_ATTR, 0);
        } else {
            reply.error(ENOENT);
        }
    }

    fn getattr (&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        info!("getattr {}", ino);
        match ino {
            1 => reply.attr(&TTL, &HELLO_DIR_ATTR),
            2 => reply.attr(&TTL, &HELLO_TXT_ATTR),
            _ => reply.error(ENOENT),
        }
    }

    fn read (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, _size: u32, reply: ReplyData) {
        info!("read ino:{} offset:{}", ino, offset);
        if ino == 2 {
            reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]);
        } else {
            reply.error(ENOENT);
        }
    }

    fn readdir (&mut self, _req: &Request, ino: u64, _fh: u64, offset: u64, mut reply: ReplyDirectory) {
        let mut data = ArgumentIterator::new(_req.data);
        info!("readdir path?? {}", data.fetch_path().to_str().unwrap());

        // FIXME correct besides field/type visibility
        //let mut data = ArgumentIterator::new(_req.data);
        //info!("readdir path?? {}", data.fetch_path().to_str().unwrap());
        info!("readdir ino:{} offset:{}", ino, offset);
        if ino == 1 {
            if offset == 0 {
                reply.add(1, 0, FileType::Directory, ".");
                reply.add(1, 1, FileType::Directory, "..");
                reply.add(2, 2, FileType::RegularFile, "hello.txt");
            }
            reply.ok();
        } else {
            reply.error(ENOENT);
        }
    }

    fn access (&mut self, _req: &Request, ino: u64, _mask: u32, reply: ReplyEmpty) {
        info!("access ino:{}", ino);
        reply.error(ENOSYS);
    }
}

fn main () {
    env_logger::init().unwrap();

    let mut mountpoint = String::new();
    let mut optstr = String::new();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("faceted-search FUSE filesystem");
        ap.refer(&mut optstr).add_option(&["-o", "--options"], Store, "comma-separated mount options");
        ap.refer(&mut mountpoint).add_argument("mountpoint", Store, "the mountpoint").required();
        ap.parse_args_or_exit();
    }

// -o plugin=foo,plugin=bar,source=/home/kellen/films/,glob=*.json,format=json,watch=true,type=directory,formatter=generic
// FIXME dynamically load plugins for globbing/formatting see:
// http://stackoverflow.com/questions/22461457/does-rust-have-a-dlopen-equivalent

    // FIXME seems weird to have to have two variable refs
    let vec;
    let mut options : &[&OsStr] = &[];
    if optstr.trim() != "" {
        vec = optstr.trim().split(",").map(|s| OsStr::new(s)).collect::<Vec<_>>();
        options = &vec;
    }

    if log_enabled!(Debug) {
        if options.len() > 0 {
            debug!("using options:");
            for s in options {
                match s.to_str() {
                    Some(y) => {debug!("\t{}", y);}
                    None => {}
                }
            }
        }
    }

    // FIMXE do this better
    let easter = UrchinFSEntry {
        display_name: "Easter Parade (1948, color)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1948"], "color" => hashset!["color"]]
    };
    let city = UrchinFSEntry {
        display_name: "The Naked City (1948, bw)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1948"], "color" => hashset!["black-and-white"]]
    };
    let vanish = UrchinFSEntry {
        display_name: "The Lady Vanishes (1938, bw)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1938"], "color" => hashset!["black-and-white"]]
    };
    let kiss = UrchinFSEntry {
        display_name: "Kiss Me Deadly (1955, bw)".to_string(),
        destination: "/home/kellen/test".to_string(),
        metadata: hashmap!["year" => hashset!["1955"], "color" => hashset!["black-and-white"]]
    };

    fuse::mount(UrchinFS {entries: vec![easter, city, vanish, kiss]}, &mountpoint, options);
}
<|endoftext|>


<commit_before>enum MyOption<T> {
  None,
  Some(T)
}

enum MyResult<T, E> {
  Ok(T),
  Err(E)
}

enum BinaryTree<T> {
  Empty,
  NonEmpty(Box<(T, BinaryTree<T>, BinaryTree<T>)>)
}

// We have to importe internal structures, cause Rust carefully hide internal structure from us.
use self::BinaryTree::*;

impl<T: Ord> BinaryTree<T> {
  fn add(&mut self, value: T) {
    match *self {
      Empty =>
        *self = NonEmpty(Box::new((value, Empty, Empty))),
      NonEmpty(ref mut node) =>
        if value <= node.0 {
          node.1.add(value);
        } else {
          node.2.add(value);
        }
    }
  }
}
<commit_msg>My favourite trailing spaces and comment improvement<commit_after>enum MyOption<T> {
  None,
  Some(T)
}

enum MyResult<T, E> {
  Ok(T),
  Err(E)
}

enum BinaryTree<T> {
  Empty,
  NonEmpty(Box<(T, BinaryTree<T>, BinaryTree<T>)>)
}

// We have to import internal structures, cause Rust carefully hides internal structures from us.
use self::BinaryTree::*;

impl<T: Ord> BinaryTree<T> {
  fn add(&mut self, value: T) {
    match *self {
      Empty =>
        *self = NonEmpty(Box::new((value, Empty, Empty))),
      NonEmpty(ref mut node) =>
        if value <= node.0 {
          node.1.add(value);
        } else {
          node.2.add(value);
        }
    }
  }
}
<|endoftext|>


<commit_before>use sdl2;

pub fn main() {
    sdl2::init([sdl2::InitVideo]);

    let window = match sdl2::video::Window::new("rust-sdl2 demo: Video", sdl2::video::PosCentered, sdl2::video::PosCentered, 800, 600, [sdl2::video::OpenGL]) {
        Ok(window) => window,
        Err(err) => fail!(fmt!("failed to create window: %s", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, [sdl2::render::Accelerated]) {
        Ok(renderer) => renderer,
        Err(err) => fail!(fmt!("failed to create renderer: %s", err))
    };

    renderer.set_draw_color(sdl2::pixels::RGB(255, 0, 0));
    renderer.clear();
    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                }
                _ => {}
            }
        }
    }

    sdl2::quit();
}
<commit_msg>Fixed Demo for Master<commit_after>use sdl2;

pub fn main() {
    sdl2::init([sdl2::InitVideo]);

    let window = match sdl2::video::Window::new("rust-sdl2 demo: Video", sdl2::video::PosCentered, sdl2::video::PosCentered, 800, 600, [sdl2::video::OpenGL]) {
        Ok(window) => window,
        Err(err) => fail!(format!("failed to create window: {}", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, [sdl2::render::Accelerated]) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("failed to create renderer: {}", err))
    };

    renderer.set_draw_color(sdl2::pixels::RGB(255, 0, 0));
    renderer.clear();
    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                }
                _ => {}
            }
        }
    }

    sdl2::quit();
}
<|endoftext|>


<commit_before>use nix::unistd::*;
use nix::unistd::Fork::*;
use nix::sys::signal::*;
use nix::sys::wait::*;
use libc::exit;

#[test]
fn test_wait_signal() {
    match fork() {
      Ok(Child) => loop { /* Wait for signal */ },
      Ok(Parent(child_pid)) => {
          kill(child_pid, SIGKILL).ok().expect("Error: Kill Failed");
          assert_eq!(waitpid(child_pid, None), Ok(WaitStatus::Signaled(child_pid, SIGKILL, false)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait_exit() {
    match fork() {
      Ok(Child) => unsafe { exit(12); },
      Ok(Parent(child_pid)) => {
          assert_eq!(waitpid(child_pid, None), Ok(WaitStatus::Exited(child_pid, 12)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}
<commit_msg>Use pause(2) in test_wait_signal<commit_after>use nix::unistd::*;
use nix::unistd::Fork::*;
use nix::sys::signal::*;
use nix::sys::wait::*;
use libc::exit;

#[test]
fn test_wait_signal() {
    match fork() {
      Ok(Child) => pause().unwrap_or(()),
      Ok(Parent(child_pid)) => {
          kill(child_pid, SIGKILL).ok().expect("Error: Kill Failed");
          assert_eq!(waitpid(child_pid, None), Ok(WaitStatus::Signaled(child_pid, SIGKILL, false)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait_exit() {
    match fork() {
      Ok(Child) => unsafe { exit(12); },
      Ok(Parent(child_pid)) => {
          assert_eq!(waitpid(child_pid, None), Ok(WaitStatus::Exited(child_pid, 12)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate askama;
extern crate iron;

use askama::Template;
use iron::{status, Response};

#[derive(Template)]
#[template(path = "hello.html")]
struct HelloTemplate<'a> {
    name: &'a str,
}

#[test]
fn test_iron() {
    let rsp = Response::with((status::Ok, HelloTemplate { name: "world" }));
    let mut buf = Vec::new();
    let _ = rsp.body.unwrap().write_body(&mut buf);
    assert_eq!(buf, "Hello, world!".as_bytes());
}
<commit_msg>Simplify Rocket test slightly<commit_after>#[macro_use]
extern crate askama;
extern crate iron;

use askama::Template;
use iron::{status, Response};

#[derive(Template)]
#[template(path = "hello.html")]
struct HelloTemplate<'a> {
    name: &'a str,
}

#[test]
fn test_iron() {
    let rsp = Response::with((status::Ok, HelloTemplate { name: "world" }));
    let mut buf = Vec::new();
    let _ = rsp.body.unwrap().write_body(&mut buf);
    assert_eq!(buf, b"Hello, world!");
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

///! Array types
use std::any::Any;
use std::convert::From;
use std::ops::Add;
use std::rc::Rc;
use std::str;
use std::string::String;

use super::bitmap::Bitmap;
use super::buffer::*;
use super::builder::*;
use super::datatypes::*;
use super::list::*;
use super::list_builder::*;

/// Trait for dealing with different types of Array at runtime when the type of the
/// array is not known in advance
pub trait Array {
    /// Returns the length of the array (number of items in the array)
    fn len(&self) -> usize;
    /// Returns the number of null values in the array
    fn null_count(&self) -> usize;
    /// Optional validity bitmap (can be None if there are no null values)
    fn validity_bitmap(&self) -> &Option<Bitmap>;
    /// Return the array as Any so that it can be downcast to a specific implementation
    fn as_any(&self) -> &Any;
}

/// Array of List<T>
pub struct ListArray<T: ArrowPrimitiveType> {
    len: usize,
    data: List<T>,
    null_count: usize,
    validity_bitmap: Option<Bitmap>,
}

impl<T> ListArray<T>
where
    T: ArrowPrimitiveType,
{
    pub fn len(&self) -> usize {
        self.len
    }

    pub fn null_count(&self) -> usize {
        self.null_count
    }

    pub fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }

    pub fn get(&self, i: usize) -> &[T] {
        self.data.get(i)
    }

    pub fn list(&self) -> &List<T> {
        &self.data
    }
}

/// Create a ListArray<T> from a List<T> without null values
impl<T> From<List<T>> for ListArray<T>
where
    T: ArrowPrimitiveType,
{
    fn from(list: List<T>) -> Self {
        let len = list.len();
        ListArray {
            len,
            data: list,
            validity_bitmap: None,
            null_count: 0,
        }
    }
}

/// Create ListArray<u8> from Vec<&'static str>
impl From<Vec<&'static str>> for ListArray<u8> {
    fn from(v: Vec<&'static str>) -> Self {
        let mut builder: ListBuilder<u8> = ListBuilder::with_capacity(v.len());
        for s in v {
            builder.push(s.as_bytes())
        }
        ListArray::from(builder.finish())
    }
}

/// Create ListArray<u8> from Vec<String>
impl From<Vec<String>> for ListArray<u8> {
    fn from(v: Vec<String>) -> Self {
        let mut builder: ListBuilder<u8> = ListBuilder::with_capacity(v.len());
        for s in v {
            builder.push(s.as_bytes())
        }
        ListArray::from(builder.finish())
    }
}

impl<T> Array for ListArray<T>
where
    T: ArrowPrimitiveType,
{
    fn len(&self) -> usize {
        self.len
    }
    fn null_count(&self) -> usize {
        self.null_count
    }
    fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }
    fn as_any(&self) -> &Any {
        self
    }
}

/// Array of T
pub struct PrimitiveArray<T: ArrowPrimitiveType> {
    len: usize,
    data: Buffer<T>,
    null_count: usize,
    validity_bitmap: Option<Bitmap>,
}

impl<T> PrimitiveArray<T>
where
    T: ArrowPrimitiveType,
{
    pub fn new(data: Buffer<T>, null_count: usize, validity_bitmap: Option<Bitmap>) -> Self {
        PrimitiveArray {
            len: data.len(),
            data: data,
            null_count,
            validity_bitmap,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn get(&self, i: usize) -> &T {
        self.data.get(i)
    }

    pub fn iter(&self) -> BufferIterator<T> {
        self.data.iter()
    }

    pub fn buffer(&self) -> &Buffer<T> {
        &self.data
    }

    /// Determine the minimum value in the array
    pub fn min(&self) -> Option<T> {
        let mut n: Option<T> = None;
        match &self.validity_bitmap {
            &Some(ref bitmap) => for i in 0..self.len {
                if bitmap.is_set(i) {
                    let mut m = self.data.get(i);
                    match n {
                        None => n = Some(*m),
                        Some(nn) => if *m < nn {
                            n = Some(*m)
                        },
                    }
                }
            },
            &None => for i in 0..self.len {
                let mut m = self.data.get(i);
                match n {
                    None => n = Some(*m),
                    Some(nn) => if *m < nn {
                        n = Some(*m)
                    },
                }
            },
        }
        n
    }

    /// Determine the maximum value in the array
    pub fn max(&self) -> Option<T> {
        let mut n: Option<T> = None;
        match &self.validity_bitmap {
            &Some(ref bitmap) => for i in 0..self.len {
                if bitmap.is_set(i) {
                    let mut m = self.data.get(i);
                    match n {
                        None => n = Some(*m),
                        Some(nn) => if *m > nn {
                            n = Some(*m)
                        },
                    }
                }
            },
            &None => for i in 0..self.len {
                let mut m = self.data.get(i);
                match n {
                    None => n = Some(*m),
                    Some(nn) => if *m > nn {
                        n = Some(*m)
                    },
                }
            },
        }
        n
    }
}

/// Implement the Add operation for types that support Add
impl<T> PrimitiveArray<T>
where
    T: ArrowPrimitiveType + Add<Output = T>,
{
    pub fn add(&self, other: &PrimitiveArray<T>) -> PrimitiveArray<T> {
        let mut builder: Builder<T> = Builder::new();
        for i in 0..self.len {
            let x = *self.data.get(i) + *other.data.get(i);
            builder.push(x);
        }
        PrimitiveArray::from(builder.finish())
    }
}

impl<T> Array for PrimitiveArray<T>
where
    T: ArrowPrimitiveType,
{
    fn len(&self) -> usize {
        self.len
    }
    fn null_count(&self) -> usize {
        self.null_count
    }
    fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }
    fn as_any(&self) -> &Any {
        self
    }
}

/// Create a BufferArray<T> from a Buffer<T> without null values
impl<T> From<Buffer<T>> for PrimitiveArray<T>
where
    T: ArrowPrimitiveType,
{
    fn from(data: Buffer<T>) -> Self {
        PrimitiveArray {
            len: data.len(),
            data: data,
            validity_bitmap: None,
            null_count: 0,
        }
    }
}

/// Create a BufferArray<T> from a Vec<T> of primitive values
impl<T> From<Vec<T>> for PrimitiveArray<T>
where
    T: ArrowPrimitiveType + 'static,
{
    fn from(vec: Vec<T>) -> Self {
        PrimitiveArray::from(Buffer::from(vec))
    }
}

/// Create a BufferArray<T> from a Vec<Optional<T>> with null handling
impl<T> From<Vec<Option<T>>> for PrimitiveArray<T>
where
    T: ArrowPrimitiveType + 'static,
{
    fn from(v: Vec<Option<T>>) -> Self {
        let mut builder: Builder<T> = Builder::with_capacity(v.len());
        builder.set_len(v.len());
        let mut null_count = 0;
        let mut validity_bitmap = Bitmap::new(v.len());
        for i in 0..v.len() {
            match v[i] {
                Some(value) => builder.set(i, value),
                None => {
                    null_count += 1;
                    validity_bitmap.clear(i);
                }
            }
        }
        PrimitiveArray::new(builder.finish(), null_count, Some(validity_bitmap))
    }
}

/// An Array of structs
pub struct StructArray {
    len: usize,
    columns: Vec<Rc<Array>>,
    null_count: usize,
    validity_bitmap: Option<Bitmap>,
}

impl StructArray {
    pub fn num_columns(&self) -> usize {
        self.columns.len()
    }
    pub fn column(&self, i: usize) -> &Rc<Array> {
        &self.columns[i]
    }
}

impl Array for StructArray {
    fn len(&self) -> usize {
        self.len
    }
    fn null_count(&self) -> usize {
        self.null_count
    }
    fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }
    fn as_any(&self) -> &Any {
        self
    }
}

/// Create a StructArray from a list of arrays representing the fields of the struct. The fields
/// must be in the same order as the schema defining the struct.
impl From<Vec<Rc<Array>>> for StructArray {
    fn from(data: Vec<Rc<Array>>) -> Self {
        StructArray {
            len: data[0].len(),
            columns: data,
            null_count: 0,
            validity_bitmap: None,
        }
    }
}

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

    #[test]
    fn array_data_from_list_u8() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push(&[1, 2, 3, 4, 5]);
        b.push(&[5, 4, 3, 2, 1]);
        let array_data = ListArray::from(b.finish());
        assert_eq!(2, array_data.len());
    }

    #[test]
    fn array_from_list_u8() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push("Hello, ".as_bytes());
        b.push("World!".as_bytes());
        let array = ListArray::from(b.finish());
        // downcast back to the data
        let array_list_u8 = array.as_any().downcast_ref::<ListArray<u8>>().unwrap();
        assert_eq!(2, array_list_u8.len());
        assert_eq!("Hello, ", str::from_utf8(array_list_u8.get(0)).unwrap());
        assert_eq!("World!", str::from_utf8(array_list_u8.get(1)).unwrap());
    }

    #[test]
    fn test_from_bool() {
        let a = PrimitiveArray::from(vec![false, false, true, false]);
        assert_eq!(4, a.len());
        assert_eq!(0, a.null_count());
    }

    #[test]
    fn test_from_f32() {
        let a = PrimitiveArray::from(vec![1.23, 2.34, 3.45, 4.56]);
        assert_eq!(4, a.len());
    }

    #[test]
    fn test_from_i32() {
        let a = PrimitiveArray::from(vec![15, 14, 13, 12, 11]);
        assert_eq!(5, a.len());
    }

    #[test]
    fn test_from_empty_vec() {
        let v: Vec<i32> = vec![];
        let a = PrimitiveArray::from(v);
        assert_eq!(0, a.len());
    }

    #[test]
    fn test_from_optional_i32() {
        let a = PrimitiveArray::from(vec![Some(1), None, Some(2), Some(3), None]);
        assert_eq!(5, a.len());
        assert_eq!(2, a.null_count());
        // 1 == not null
        match a.validity_bitmap() {
            &Some(ref validity_bitmap) => {
                assert_eq!(true, validity_bitmap.is_set(0));
                assert_eq!(false, validity_bitmap.is_set(1));
                assert_eq!(true, validity_bitmap.is_set(2));
                assert_eq!(true, validity_bitmap.is_set(3));
                assert_eq!(false, validity_bitmap.is_set(4));
            }
            _ => panic!(),
        }
    }

    #[test]
    fn test_struct() {
        let a: Rc<Array> = Rc::new(PrimitiveArray::from(Buffer::from(vec![1, 2, 3, 4, 5])));
        let b: Rc<Array> = Rc::new(PrimitiveArray::from(Buffer::from(vec![
            1.1, 2.2, 3.3, 4.4, 5.5
        ])));

        let s = StructArray::from(vec![a, b]);
        assert_eq!(2, s.num_columns());
        assert_eq!(0, s.null_count());
    }

    #[test]
    fn test_buffer_array_min_max() {
        let a = PrimitiveArray::from(Buffer::from(vec![5, 6, 7, 8, 9]));
        assert_eq!(5, a.min().unwrap());
        assert_eq!(9, a.max().unwrap());
    }

    #[test]
    fn test_buffer_array_min_max_with_nulls() {
        let a = PrimitiveArray::from(vec![Some(5), None, None, Some(8), Some(9)]);
        assert_eq!(5, a.min().unwrap());
        assert_eq!(9, a.max().unwrap());
    }

}
<commit_msg>ARROW-2691: [Rust] Update code formatting with latest Rust stable<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

///! Array types
use std::any::Any;
use std::convert::From;
use std::ops::Add;
use std::rc::Rc;
use std::str;
use std::string::String;

use super::bitmap::Bitmap;
use super::buffer::*;
use super::builder::*;
use super::datatypes::*;
use super::list::*;
use super::list_builder::*;

/// Trait for dealing with different types of Array at runtime when the type of the
/// array is not known in advance
pub trait Array {
    /// Returns the length of the array (number of items in the array)
    fn len(&self) -> usize;
    /// Returns the number of null values in the array
    fn null_count(&self) -> usize;
    /// Optional validity bitmap (can be None if there are no null values)
    fn validity_bitmap(&self) -> &Option<Bitmap>;
    /// Return the array as Any so that it can be downcast to a specific implementation
    fn as_any(&self) -> &Any;
}

/// Array of List<T>
pub struct ListArray<T: ArrowPrimitiveType> {
    len: usize,
    data: List<T>,
    null_count: usize,
    validity_bitmap: Option<Bitmap>,
}

impl<T> ListArray<T>
where
    T: ArrowPrimitiveType,
{
    pub fn len(&self) -> usize {
        self.len
    }

    pub fn null_count(&self) -> usize {
        self.null_count
    }

    pub fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }

    pub fn get(&self, i: usize) -> &[T] {
        self.data.get(i)
    }

    pub fn list(&self) -> &List<T> {
        &self.data
    }
}

/// Create a ListArray<T> from a List<T> without null values
impl<T> From<List<T>> for ListArray<T>
where
    T: ArrowPrimitiveType,
{
    fn from(list: List<T>) -> Self {
        let len = list.len();
        ListArray {
            len,
            data: list,
            validity_bitmap: None,
            null_count: 0,
        }
    }
}

/// Create ListArray<u8> from Vec<&'static str>
impl From<Vec<&'static str>> for ListArray<u8> {
    fn from(v: Vec<&'static str>) -> Self {
        let mut builder: ListBuilder<u8> = ListBuilder::with_capacity(v.len());
        for s in v {
            builder.push(s.as_bytes())
        }
        ListArray::from(builder.finish())
    }
}

/// Create ListArray<u8> from Vec<String>
impl From<Vec<String>> for ListArray<u8> {
    fn from(v: Vec<String>) -> Self {
        let mut builder: ListBuilder<u8> = ListBuilder::with_capacity(v.len());
        for s in v {
            builder.push(s.as_bytes())
        }
        ListArray::from(builder.finish())
    }
}

impl<T> Array for ListArray<T>
where
    T: ArrowPrimitiveType,
{
    fn len(&self) -> usize {
        self.len
    }
    fn null_count(&self) -> usize {
        self.null_count
    }
    fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }
    fn as_any(&self) -> &Any {
        self
    }
}

/// Array of T
pub struct PrimitiveArray<T: ArrowPrimitiveType> {
    len: usize,
    data: Buffer<T>,
    null_count: usize,
    validity_bitmap: Option<Bitmap>,
}

impl<T> PrimitiveArray<T>
where
    T: ArrowPrimitiveType,
{
    pub fn new(data: Buffer<T>, null_count: usize, validity_bitmap: Option<Bitmap>) -> Self {
        PrimitiveArray {
            len: data.len(),
            data: data,
            null_count,
            validity_bitmap,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn get(&self, i: usize) -> &T {
        self.data.get(i)
    }

    pub fn iter(&self) -> BufferIterator<T> {
        self.data.iter()
    }

    pub fn buffer(&self) -> &Buffer<T> {
        &self.data
    }

    /// Determine the minimum value in the array
    pub fn min(&self) -> Option<T> {
        let mut n: Option<T> = None;
        match &self.validity_bitmap {
            &Some(ref bitmap) => for i in 0..self.len {
                if bitmap.is_set(i) {
                    let mut m = self.data.get(i);
                    match n {
                        None => n = Some(*m),
                        Some(nn) => if *m < nn {
                            n = Some(*m)
                        },
                    }
                }
            },
            &None => for i in 0..self.len {
                let mut m = self.data.get(i);
                match n {
                    None => n = Some(*m),
                    Some(nn) => if *m < nn {
                        n = Some(*m)
                    },
                }
            },
        }
        n
    }

    /// Determine the maximum value in the array
    pub fn max(&self) -> Option<T> {
        let mut n: Option<T> = None;
        match &self.validity_bitmap {
            &Some(ref bitmap) => for i in 0..self.len {
                if bitmap.is_set(i) {
                    let mut m = self.data.get(i);
                    match n {
                        None => n = Some(*m),
                        Some(nn) => if *m > nn {
                            n = Some(*m)
                        },
                    }
                }
            },
            &None => for i in 0..self.len {
                let mut m = self.data.get(i);
                match n {
                    None => n = Some(*m),
                    Some(nn) => if *m > nn {
                        n = Some(*m)
                    },
                }
            },
        }
        n
    }
}

/// Implement the Add operation for types that support Add
impl<T> PrimitiveArray<T>
where
    T: ArrowPrimitiveType + Add<Output = T>,
{
    pub fn add(&self, other: &PrimitiveArray<T>) -> PrimitiveArray<T> {
        let mut builder: Builder<T> = Builder::new();
        for i in 0..self.len {
            let x = *self.data.get(i) + *other.data.get(i);
            builder.push(x);
        }
        PrimitiveArray::from(builder.finish())
    }
}

impl<T> Array for PrimitiveArray<T>
where
    T: ArrowPrimitiveType,
{
    fn len(&self) -> usize {
        self.len
    }
    fn null_count(&self) -> usize {
        self.null_count
    }
    fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }
    fn as_any(&self) -> &Any {
        self
    }
}

/// Create a BufferArray<T> from a Buffer<T> without null values
impl<T> From<Buffer<T>> for PrimitiveArray<T>
where
    T: ArrowPrimitiveType,
{
    fn from(data: Buffer<T>) -> Self {
        PrimitiveArray {
            len: data.len(),
            data: data,
            validity_bitmap: None,
            null_count: 0,
        }
    }
}

/// Create a BufferArray<T> from a Vec<T> of primitive values
impl<T> From<Vec<T>> for PrimitiveArray<T>
where
    T: ArrowPrimitiveType + 'static,
{
    fn from(vec: Vec<T>) -> Self {
        PrimitiveArray::from(Buffer::from(vec))
    }
}

/// Create a BufferArray<T> from a Vec<Optional<T>> with null handling
impl<T> From<Vec<Option<T>>> for PrimitiveArray<T>
where
    T: ArrowPrimitiveType + 'static,
{
    fn from(v: Vec<Option<T>>) -> Self {
        let mut builder: Builder<T> = Builder::with_capacity(v.len());
        builder.set_len(v.len());
        let mut null_count = 0;
        let mut validity_bitmap = Bitmap::new(v.len());
        for i in 0..v.len() {
            match v[i] {
                Some(value) => builder.set(i, value),
                None => {
                    null_count += 1;
                    validity_bitmap.clear(i);
                }
            }
        }
        PrimitiveArray::new(builder.finish(), null_count, Some(validity_bitmap))
    }
}

/// An Array of structs
pub struct StructArray {
    len: usize,
    columns: Vec<Rc<Array>>,
    null_count: usize,
    validity_bitmap: Option<Bitmap>,
}

impl StructArray {
    pub fn num_columns(&self) -> usize {
        self.columns.len()
    }
    pub fn column(&self, i: usize) -> &Rc<Array> {
        &self.columns[i]
    }
}

impl Array for StructArray {
    fn len(&self) -> usize {
        self.len
    }
    fn null_count(&self) -> usize {
        self.null_count
    }
    fn validity_bitmap(&self) -> &Option<Bitmap> {
        &self.validity_bitmap
    }
    fn as_any(&self) -> &Any {
        self
    }
}

/// Create a StructArray from a list of arrays representing the fields of the struct. The fields
/// must be in the same order as the schema defining the struct.
impl From<Vec<Rc<Array>>> for StructArray {
    fn from(data: Vec<Rc<Array>>) -> Self {
        StructArray {
            len: data[0].len(),
            columns: data,
            null_count: 0,
            validity_bitmap: None,
        }
    }
}

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

    #[test]
    fn array_data_from_list_u8() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push(&[1, 2, 3, 4, 5]);
        b.push(&[5, 4, 3, 2, 1]);
        let array_data = ListArray::from(b.finish());
        assert_eq!(2, array_data.len());
    }

    #[test]
    fn array_from_list_u8() {
        let mut b: ListBuilder<u8> = ListBuilder::new();
        b.push("Hello, ".as_bytes());
        b.push("World!".as_bytes());
        let array = ListArray::from(b.finish());
        // downcast back to the data
        let array_list_u8 = array.as_any().downcast_ref::<ListArray<u8>>().unwrap();
        assert_eq!(2, array_list_u8.len());
        assert_eq!("Hello, ", str::from_utf8(array_list_u8.get(0)).unwrap());
        assert_eq!("World!", str::from_utf8(array_list_u8.get(1)).unwrap());
    }

    #[test]
    fn test_from_bool() {
        let a = PrimitiveArray::from(vec![false, false, true, false]);
        assert_eq!(4, a.len());
        assert_eq!(0, a.null_count());
    }

    #[test]
    fn test_from_f32() {
        let a = PrimitiveArray::from(vec![1.23, 2.34, 3.45, 4.56]);
        assert_eq!(4, a.len());
    }

    #[test]
    fn test_from_i32() {
        let a = PrimitiveArray::from(vec![15, 14, 13, 12, 11]);
        assert_eq!(5, a.len());
    }

    #[test]
    fn test_from_empty_vec() {
        let v: Vec<i32> = vec![];
        let a = PrimitiveArray::from(v);
        assert_eq!(0, a.len());
    }

    #[test]
    fn test_from_optional_i32() {
        let a = PrimitiveArray::from(vec![Some(1), None, Some(2), Some(3), None]);
        assert_eq!(5, a.len());
        assert_eq!(2, a.null_count());
        // 1 == not null
        match a.validity_bitmap() {
            &Some(ref validity_bitmap) => {
                assert_eq!(true, validity_bitmap.is_set(0));
                assert_eq!(false, validity_bitmap.is_set(1));
                assert_eq!(true, validity_bitmap.is_set(2));
                assert_eq!(true, validity_bitmap.is_set(3));
                assert_eq!(false, validity_bitmap.is_set(4));
            }
            _ => panic!(),
        }
    }

    #[test]
    fn test_struct() {
        let a: Rc<Array> = Rc::new(PrimitiveArray::from(Buffer::from(vec![1, 2, 3, 4, 5])));
        let b: Rc<Array> = Rc::new(PrimitiveArray::from(Buffer::from(vec![
            1.1, 2.2, 3.3, 4.4, 5.5,
        ])));

        let s = StructArray::from(vec![a, b]);
        assert_eq!(2, s.num_columns());
        assert_eq!(0, s.null_count());
    }

    #[test]
    fn test_buffer_array_min_max() {
        let a = PrimitiveArray::from(Buffer::from(vec![5, 6, 7, 8, 9]));
        assert_eq!(5, a.min().unwrap());
        assert_eq!(9, a.max().unwrap());
    }

    #[test]
    fn test_buffer_array_min_max_with_nulls() {
        let a = PrimitiveArray::from(vec![Some(5), None, None, Some(8), Some(9)]);
        assert_eq!(5, a.min().unwrap());
        assert_eq!(9, a.max().unwrap());
    }

}
<|endoftext|>


<commit_before>extern crate collections;
extern crate sync;
#[cfg(test)]
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use sync::{Arc, RWLock};

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	directory: TempDir,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	pageId: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint) -> BufferManager {
		let h = HashMap::with_capacity(size);
		let dir = match TempDir::new("buffermanager") {
			Some(temp_dir) => temp_dir,
			None => fail!("creation of temporary directory"),
		};
		BufferManager {size: size, entries: h, directory: dir}
	}

	fn openOrCreate(&self, pageId: u64) -> File {
		let page_path = self.directory.path();
		let file_path = page_path.join(pageId.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(e) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						f.write([0_u8, ..4 * 1024]);
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn loadPage(&mut self, pageId: u64) {
		if self.entries.len() == self.size {
			self.evictPage();
		}

		let mut file_handle = self.openOrCreate(pageId);
		let content = match file_handle.read_exact(4*1024) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, pageId: pageId};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(pageId, entry);
	}

	fn evictPage(&mut self) {
		// TODO delete a random page
		// evicting is hard, let's go shopping
	}

	pub fn fixPage(&mut self, pageId: u64, exclusive: bool) -> Option<Arc<RWLock<BufferFrame>>> {
		// TODO
		if !self.entries.contains_key(&pageId) {
			self.loadPage(pageId);
		}
		let entry = self.entries.get(&pageId);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfixPage(&mut self, frame: Arc<RWLock<BufferFrame>>, isDirty: bool) {
		if !isDirty {
			return;
		}
		let frame = frame.read();
		self.writePage(frame.pageId, frame.get_data());
	}

	fn writePage(&mut self, pageId: u64, data: &[u8]) {
		// TODO: write page back to disk
		println!("Writing {}", data);
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

#[test]
fn test_create() {
	let mut bm = BufferManager::new(16);
	let pageref = match bm.fixPage(42, false) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		println!("data: {}", Vec::from_slice(data));
	}
	bm.unfixPage(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use rand::task_rng;
	use rand::distributions::{IndependentSample, Range};
	use std::task::spawn;

	let pages_in_ram = 20;
	let pages_on_disk: u64 = 20;
	let thread_count = 10;
	let mut buffermanager = BufferManager::new(pages_in_ram);

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fixPage(i, true) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfixPage(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start read/write threads
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		spawn(proc() {
			let is_write = random::<bool>();
			let between = Range::new(0, pages_on_disk);
			let mut rng = rand::task_rng();
			let page_number = between.ind_sample(&mut rng);
			let mut bm = bm.write();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			if is_write {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				{
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
				}
				bm.unfixPage(bf, is_write);
			} else {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				bm.unfixPage(bf, is_write);
			}
		});
	}
}
<commit_msg>Fixed some warnings<commit_after>extern crate collections;
extern crate sync;
#[cfg(test)]
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use sync::{Arc, RWLock};

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	directory: TempDir,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	pageId: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint) -> BufferManager {
		let h = HashMap::with_capacity(size);
		let dir = match TempDir::new("buffermanager") {
			Some(temp_dir) => temp_dir,
			None => fail!("creation of temporary directory"),
		};
		BufferManager {size: size, entries: h, directory: dir}
	}

	fn openOrCreate(&self, pageId: u64) -> File {
		let page_path = self.directory.path();
		let file_path = page_path.join(pageId.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn loadPage(&mut self, pageId: u64) {
		if self.entries.len() == self.size {
			self.evictPage();
		}

		let mut file_handle = self.openOrCreate(pageId);
		let content = match file_handle.read_exact(4*1024) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, pageId: pageId};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(pageId, entry);
	}

	fn evictPage(&mut self) {
		// TODO delete a random page
		// evicting is hard, let's go shopping
	}

	pub fn fixPage(&mut self, pageId: u64, exclusive: bool) -> Option<Arc<RWLock<BufferFrame>>> {
		// TODO
		if !self.entries.contains_key(&pageId) {
			self.loadPage(pageId);
		}
		let entry = self.entries.get(&pageId);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfixPage(&mut self, frame: Arc<RWLock<BufferFrame>>, isDirty: bool) {
		if !isDirty {
			return;
		}
		let frame = frame.read();
		self.writePage(frame.pageId, frame.get_data());
	}

	fn writePage(&mut self, pageId: u64, data: &[u8]) {
		// TODO: write page back to disk
		println!("Writing {}", data);
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

#[test]
fn test_create() {
	let mut bm = BufferManager::new(16);
	let pageref = match bm.fixPage(42, false) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		println!("data: {}", Vec::from_slice(data));
	}
	bm.unfixPage(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use rand::task_rng;
	use rand::distributions::{IndependentSample, Range};
	use std::task::spawn;

	let pages_in_ram = 20;
	let pages_on_disk: u64 = 20;
	let thread_count = 10;
	let mut buffermanager = BufferManager::new(pages_in_ram);

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fixPage(i, true) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfixPage(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start read/write threads
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		spawn(proc() {
			let is_write = random::<bool>();
			let between = Range::new(0, pages_on_disk);
			let mut rng = rand::task_rng();
			let page_number = between.ind_sample(&mut rng);
			let mut bm = bm.write();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			if is_write {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				{
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
				}
				bm.unfixPage(bf, is_write);
			} else {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				bm.unfixPage(bf, is_write);
			}
		});
	}
}
<|endoftext|>


<commit_before>extern crate collections;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};

enum State {
	Available,
	Exclusive,
}

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	directory: TempDir,
}

struct BufferEntry {
	state: State,
	frame: BufferFrame,
}

struct BufferFrame {
	data: Vec<u8>,
}

impl BufferManager {
	pub fn new(size: uint) -> BufferManager {
		let h = HashMap::with_capacity(size);
		let dir = match TempDir::new("externalsort") {
			Some(temp_dir) => temp_dir,
			None => fail!("creation of temporary directory"),
		};
		BufferManager {size: size, entries: h, directory: dir}
	}

	fn openOrCreate(&self, pageId: u64) -> File {
		let page_path = self.directory.path();
		let file_path = page_path.join(pageId.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(e) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						f.write([0_u8, ..4 * 1024]);
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}, e"),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn loadPage(&mut self, pageId: u64) {
		if self.entries.len() == self.size {
			self.evictPage();
		}

		// TODO: open file, load page
		let mut file_handle = self.openOrCreate(pageId);
		let buffer = [0_u8, ..4*1024];

		let content = match file_handle.read_exact(4*1024) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content};
		let entry = BufferEntry {state: Available, frame: frame};
		self.entries.insert(pageId, entry);
	}

	fn evictPage(&mut self) {
		// TODO delete a random page
	}

	pub fn fixPage(pageId: u64, exclusive: bool) -> Option<BufferFrame> {
		// TODO
		None
	}

	pub fn unfixPage(frame: BufferFrame, isDirty: bool) {
		// TODO
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * getData returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn getData<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
}

fn main() {
	println!("Rewrite me into a test");
}
<commit_msg>Using RWLock and Arcs now<commit_after>extern crate collections;
extern crate sync;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use sync::{Arc, RWLock};

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	directory: TempDir,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	pageId: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint) -> BufferManager {
		let h = HashMap::with_capacity(size);
		let dir = match TempDir::new("buffermanager") {
			Some(temp_dir) => temp_dir,
			None => fail!("creation of temporary directory"),
		};
		BufferManager {size: size, entries: h, directory: dir}
	}

	fn openOrCreate(&self, pageId: u64) -> File {
		let page_path = self.directory.path();
		let file_path = page_path.join(pageId.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(e) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						f.write([0_u8, ..4 * 1024]);
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}, e"),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn loadPage(&mut self, pageId: u64) {
		if self.entries.len() == self.size {
			self.evictPage();
		}

		let mut file_handle = self.openOrCreate(pageId);
		let content = match file_handle.read_exact(4*1024) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, pageId: pageId};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(pageId, entry);
	}

	fn evictPage(&mut self) {
		// TODO delete a random page
	}

	pub fn fixPage(&mut self, pageId: u64, exclusive: bool) -> Option<Arc<RWLock<BufferFrame>>> {
		// TODO
		if !self.entries.contains_key(&pageId) {
			self.loadPage(pageId);
		}
		let entry = self.entries.get(&pageId);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfixPage(&mut self, frame: Arc<RWLock<BufferFrame>>, isDirty: bool) {
		if !isDirty {
			return;
		}
		let frame = frame.read();
		self.writePage(frame.pageId, frame.get_data());
	}

	fn writePage(&mut self, pageId: u64, data: &[u8]) {
		// TODO: write page back to disk
		println!("Writing {}", data);
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

#[test]
fn test_create() {
	let _ = BufferManager::new(16);
}
<|endoftext|>