<commit_before>//! A "compatibility layer" for spanning XP and Windows 7
//!
//! The standard library currently binds many functions that are not available
//! on Windows XP, but we would also like to support building executables that
//! run on XP. To do this we specify all non-XP APIs as having a fallback
//! implementation to do something reasonable.
//!
//! This dynamic runtime detection of whether a function is available is
//! implemented with `GetModuleHandle` and `GetProcAddress` paired with a
//! static-per-function which caches the result of the first check. In this
//! manner we pay a semi-large one-time cost up front for detecting whether a
//! function is available but afterwards it's just a load and a jump.

use crate::ffi::CString;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::c;

pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
    let mut module: Vec<u16> = module.encode_utf16().collect();
    module.push(0);
    let symbol = CString::new(symbol).unwrap();
    unsafe {
        let handle = c::GetModuleHandleW(module.as_ptr());
        match c::GetProcAddress(handle, symbol.as_ptr()) as usize {
            0 => None,
            n => Some(n),
        }
    }
}

pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
                  fallback: usize) -> usize {
    let value = lookup(module, symbol).unwrap_or(fallback);
    ptr.store(value, Ordering::SeqCst);
    value
}

macro_rules! compat_fn {
    ($module:ident: $(
        pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
                                  -> $rettype:ty {
            $($body:expr);*
        }
    )*) => ($(
        #[allow(unused_variables)]
        pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
            use crate::sync::atomic::{AtomicUsize, Ordering};
            use crate::mem;
            type F = unsafe extern "system" fn($($argtype),*) -> $rettype;

            static PTR: AtomicUsize = AtomicUsize::new(0);

            fn load() -> usize {
                crate::sys::compat::store_func(&PTR,
                                          stringify!($module),
                                          stringify!($symbol),
                                          fallback as usize)
            }
            unsafe extern "system" fn fallback($($argname: $argtype),*)
                                               -> $rettype {
                $($body);*
            }

            let addr = match PTR.load(Ordering::SeqCst) {
                0 => load(),
                n => n,
            };
            mem::transmute::<usize, F>(addr)($($argname),*)
        }
    )*)
}
<commit_msg>libstd: windows: compat: Allow use of attributes<commit_after>//! A "compatibility layer" for spanning XP and Windows 7
//!
//! The standard library currently binds many functions that are not available
//! on Windows XP, but we would also like to support building executables that
//! run on XP. To do this we specify all non-XP APIs as having a fallback
//! implementation to do something reasonable.
//!
//! This dynamic runtime detection of whether a function is available is
//! implemented with `GetModuleHandle` and `GetProcAddress` paired with a
//! static-per-function which caches the result of the first check. In this
//! manner we pay a semi-large one-time cost up front for detecting whether a
//! function is available but afterwards it's just a load and a jump.

use crate::ffi::CString;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::c;

pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
    let mut module: Vec<u16> = module.encode_utf16().collect();
    module.push(0);
    let symbol = CString::new(symbol).unwrap();
    unsafe {
        let handle = c::GetModuleHandleW(module.as_ptr());
        match c::GetProcAddress(handle, symbol.as_ptr()) as usize {
            0 => None,
            n => Some(n),
        }
    }
}

pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
                  fallback: usize) -> usize {
    let value = lookup(module, symbol).unwrap_or(fallback);
    ptr.store(value, Ordering::SeqCst);
    value
}

macro_rules! compat_fn {
    ($module:ident: $(
        $(#[$meta:meta])*
        pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
                                  -> $rettype:ty {
            $($body:expr);*
        }
    )*) => ($(
        #[allow(unused_variables)]
        $(#[$meta])*
        pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
            use crate::sync::atomic::{AtomicUsize, Ordering};
            use crate::mem;
            type F = unsafe extern "system" fn($($argtype),*) -> $rettype;

            static PTR: AtomicUsize = AtomicUsize::new(0);

            fn load() -> usize {
                crate::sys::compat::store_func(&PTR,
                                          stringify!($module),
                                          stringify!($symbol),
                                          fallback as usize)
            }
            unsafe extern "system" fn fallback($($argname: $argtype),*)
                                               -> $rettype {
                $($body);*
            }

            let addr = match PTR.load(Ordering::SeqCst) {
                0 => load(),
                n => n,
            };
            mem::transmute::<usize, F>(addr)($($argname),*)
        }
    )*)
}
<|endoftext|>


<commit_before>#![feature(unmarked_api)]

extern crate graphite;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rustc_serialize;
extern crate docopt;
extern crate time;

use graphite::carbon;

use std::path::Path;

use docopt::Docopt;
static USAGE: &'static str = "
Carbon is the network service for writing data to disk

Usage: carbon [--port PORT] [--bind HOST] [--chan DEPTH]

Options:
    --bind HOST             host to bind to [default: 0.0.0.0:2003]
    --chan DEPTH            how many carbon messages can be in-flight [default: 1000]
    --storage-path STORAGE_PATH  where to find the whisper file [default: /tmp]
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_bind: String,
    flag_chan: usize,
    flag_storage_path: String
}

pub fn main(){
    env_logger::init().unwrap();
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let bind_spec = unsafe {
        args.flag_bind.slice_unchecked(0, args.flag_bind.len())
    };

    let config = carbon::Config{
        bind_spec: bind_spec,
        chan_depth: args.flag_chan,
        base_path: Path::new(&args.flag_storage_path)
    };

    info!("starting carbon server...");
    carbon::udp::run_server(&config).unwrap();
}
<commit_msg>Ugh. Runtime error for cli parsing.<commit_after>#![feature(unmarked_api)]

extern crate graphite;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rustc_serialize;
extern crate docopt;
extern crate time;

use graphite::carbon;

use std::path::Path;

use docopt::Docopt;
static USAGE: &'static str = "
Carbon is the network service for writing data to disk

Usage: carbon [--port PORT] [--bind HOST] [--chan DEPTH]

Options:
    --bind HOST             host to bind to [default: 0.0.0.0:2003]
    --chan DEPTH            how many carbon messages can be in-flight [default: 1000]
    --storage-path STORAGEPATH  where to find the whisper file [default: /tmp]
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_bind: String,
    flag_chan: usize,
    flag_storage_path: String
}

pub fn main(){
    env_logger::init().unwrap();
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let bind_spec = unsafe {
        args.flag_bind.slice_unchecked(0, args.flag_bind.len())
    };

    let config = carbon::Config{
        bind_spec: bind_spec,
        chan_depth: args.flag_chan,
        base_path: Path::new(&args.flag_storage_path)
    };

    info!("starting carbon server...");
    carbon::udp::run_server(&config).unwrap();
}
<|endoftext|>


<commit_before>// Build script.
//
// This program is run by Cargo when building cranelift-codegen. It is used to generate Rust code from
// the language definitions in the cranelift-codegen/meta directory.
//
// Environment:
//
// OUT_DIR
//     Directory where generated files should be placed.
//
// TARGET
//     Target triple provided by Cargo.
//
// The build script expects to be run from the directory where this build.rs file lives. The
// current directory is used to find the sources.

use cranelift_codegen_meta as meta;

use std::env;
use std::process;
use std::time::Instant;

fn main() {
    let start_time = Instant::now();

    let out_dir = env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set");
    let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set");

    // Configure isa targets cfg.
    let isa_targets = meta::isa::Isa::all()
        .into_iter()
        .cloned()
        .filter(|isa| {
            let env_key = format!("CARGO_FEATURE_{}", isa.to_string().to_uppercase());
            env::var(env_key).is_ok()
        })
        .collect::<Vec<_>>();

    let isas = if isa_targets.is_empty() {
        // Try to match native target.
        let target_name = target_triple.split('-').next().unwrap();
        let isa = meta::isa_from_arch(&target_name).expect("error when identifying target");
        println!("cargo:rustc-cfg=feature=\"{}\"", isa);
        vec![isa]
    } else {
        isa_targets
    };

    let cur_dir = env::current_dir().expect("Can't access current working directory");
    let crate_dir = cur_dir.as_path();

    // Make sure we rebuild if this build script changes (will not happen with
    // if the path to this file contains non-UTF-8 bytes).
    println!(
        "cargo:rerun-if-changed={}",
        crate_dir.join("build.rs").to_str().unwrap()
    );

    if let Err(err) = meta::generate(&isas, &out_dir) {
        eprintln!("Error: {}", err);
        process::exit(1);
    }

    if let Ok(_) = env::var("CRANELIFT_VERBOSE") {
        for isa in &isas {
            println!("cargo:warning=Includes support for {} ISA", isa.to_string());
        }
        println!(
            "cargo:warning=Build step took {:?}.",
            Instant::now() - start_time
        );
        println!("cargo:warning=Generated files are in {}", out_dir);
    }
}
<commit_msg>Use array::iter<commit_after>// Build script.
//
// This program is run by Cargo when building cranelift-codegen. It is used to generate Rust code from
// the language definitions in the cranelift-codegen/meta directory.
//
// Environment:
//
// OUT_DIR
//     Directory where generated files should be placed.
//
// TARGET
//     Target triple provided by Cargo.
//
// The build script expects to be run from the directory where this build.rs file lives. The
// current directory is used to find the sources.

use cranelift_codegen_meta as meta;

use std::env;
use std::process;
use std::time::Instant;

fn main() {
    let start_time = Instant::now();

    let out_dir = env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set");
    let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set");

    // Configure isa targets cfg.
    let isa_targets = meta::isa::Isa::all()
        .iter()
        .cloned()
        .filter(|isa| {
            let env_key = format!("CARGO_FEATURE_{}", isa.to_string().to_uppercase());
            env::var(env_key).is_ok()
        })
        .collect::<Vec<_>>();

    let isas = if isa_targets.is_empty() {
        // Try to match native target.
        let target_name = target_triple.split('-').next().unwrap();
        let isa = meta::isa_from_arch(&target_name).expect("error when identifying target");
        println!("cargo:rustc-cfg=feature=\"{}\"", isa);
        vec![isa]
    } else {
        isa_targets
    };

    let cur_dir = env::current_dir().expect("Can't access current working directory");
    let crate_dir = cur_dir.as_path();

    // Make sure we rebuild if this build script changes (will not happen with
    // if the path to this file contains non-UTF-8 bytes).
    println!(
        "cargo:rerun-if-changed={}",
        crate_dir.join("build.rs").to_str().unwrap()
    );

    if let Err(err) = meta::generate(&isas, &out_dir) {
        eprintln!("Error: {}", err);
        process::exit(1);
    }

    if let Ok(_) = env::var("CRANELIFT_VERBOSE") {
        for isa in &isas {
            println!("cargo:warning=Includes support for {} ISA", isa.to_string());
        }
        println!(
            "cargo:warning=Build step took {:?}.",
            Instant::now() - start_time
        );
        println!("cargo:warning=Generated files are in {}", out_dir);
    }
}
<|endoftext|>


<commit_before>//   Copyright Dzmitry Malyshau 2017
//
//   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.

use std::f32::consts::PI;
use Vertex;
use super::{Quad, Polygon, Triangle};
use super::generators::{SharedVertex, IndexedPolygon};

/// Represents a cylinder with radius of 1, height of 2,
/// and centered at (0, 0, 0) pointing up (to 0, 0, 1).
#[derive(Clone, Copy)]
pub struct Cylinder {
    u: usize,
    h: isize,
    sub_u: usize,
    sub_h: isize,
}

const TOP: Vertex = Vertex {
    pos: [0., 0., 1.],
    normal: [0., 0., 1.],
};

const BOT: Vertex = Vertex {
    pos: [0., 0., -1.],
    normal: [0., 0., -1.],
};

impl Cylinder {
    /// Create a new cylinder.
    /// `u` is the number of points across the radius.
    pub fn new(u: usize) -> Self {
        assert!(u > 1);
        Cylinder {
            u: 0,
            h: -1,
            sub_u: u,
            sub_h: 1,
        }
    }

    /// Create a new subdivided cylinder.
    /// `u` is the number of points across the radius.
    /// `h` is the number of segments across the height.
    pub fn subdivide(u: usize, h: usize) -> Self {
        assert!(u > 1 && h > 0);
        Cylinder {
            u: 0,
            h: -1,
            sub_u: u,
            sub_h: h as isize,
        }
    }

    fn vert(&self, u: usize, h: isize) -> Vertex {
        debug_assert!(u <= self.sub_u);
        let a = (u as f32 / self.sub_u as f32) * PI * 2.;
        let n = [a.cos(), a.sin(), 0.];
        let (hc, normal) = if h < 0 {
            debug_assert_eq!(h, -1);
            (0, [0., 0., -1.])
        } else if h > self.sub_h {
            debug_assert_eq!(h, self.sub_h + 1);
            (self.sub_h, [0., 0., 1.])
        } else {
            (h, n)
        };
        let z = (hc as f32 / self.sub_h as f32) * 2. - 1.;
        Vertex {
            pos: [n[0], n[1], z],
            normal,
        }
    }
}

impl Iterator for Cylinder {
    type Item = Polygon<Vertex>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        let n = self.sub_u * (1 + self.sub_h - self.h) as usize - self.u;
        (n, Some(n))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if self.u == self.sub_u {
            if self.h >= self.sub_h {
                return None;
            }
            self.u = 0;
            self.h += 1;
        }

        let u = self.u;
        self.u += 1;
        // mathematically, reaching `u + 1 == sub_u` should trivially resolve,
        // because sin(2pi) == sin(0), but rounding errors go in the way.
        let u1 = self.u % self.sub_u;

        let x = self.vert(u, self.h);
        let y = self.vert(u1, self.h);

        Some(if self.h < 0 {
            Polygon::PolyTri(Triangle::new(x, BOT, y))
        } else if self.h == self.sub_h {
            Polygon::PolyTri(Triangle::new(x, y, TOP))
        } else {
            let z = self.vert(u1, self.h + 1);
            let w = self.vert(u, self.h + 1);
            Polygon::PolyQuad(Quad::new(x, y, z, w))
        })
    }
}

impl SharedVertex<Vertex> for Cylinder {
    fn shared_vertex(&self, idx: usize) -> Vertex {
        if idx == 0 {
            BOT
        } else if idx == self.shared_vertex_count() - 1 {
            TOP
        } else {
            // skip the bottom center
            let idx = idx - 1;
            let u = idx % self.sub_u;
            let h = (idx / self.sub_u) as isize - 1;
            self.vert(u, h)
        }
    }

    fn shared_vertex_count(&self) -> usize {
        (3 + self.sub_h) as usize * self.sub_u + 2
    }
}

impl IndexedPolygon<Polygon<usize>> for Cylinder {
    fn indexed_polygon(&self, idx: usize) -> Polygon<usize> {
        let u = idx % self.sub_u;
        let u1 = (idx + 1) % self.sub_u;
        let h = (idx / self.sub_u) as isize - 1;
        let base = 1 + idx - u;
        if h < 0 {
            let start = 0;
            Polygon::PolyTri(Triangle::new(base + u, start, base + u1))
        } else if h == self.sub_h {
            let end = self.shared_vertex_count() - 1;
            Polygon::PolyTri(Triangle::new(base + u, base + u1, end))
        } else {
            Polygon::PolyQuad(Quad::new(base + u,
                                        base + u1,
                                        base + u1 + self.sub_u,
                                        base + u + self.sub_u))
        }
    }

    fn indexed_polygon_count(&self) -> usize {
        (2 + self.sub_h) as usize * self.sub_u
    }
}
<commit_msg>Fix the normals for the bottom edge loop.<commit_after>//   Copyright Dzmitry Malyshau 2017
//
//   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.

use std::f32::consts::PI;
use Vertex;
use super::{Quad, Polygon, Triangle};
use super::generators::{SharedVertex, IndexedPolygon};

/// Represents a cylinder with radius of 1, height of 2,
/// and centered at (0, 0, 0) pointing up (to 0, 0, 1).
#[derive(Clone, Copy)]
pub struct Cylinder {
    u: usize,
    h: isize,
    sub_u: usize,
    sub_h: isize,
}

const TOP: Vertex = Vertex {
    pos: [0., 0., 1.],
    normal: [0., 0., 1.],
};

const BOT: Vertex = Vertex {
    pos: [0., 0., -1.],
    normal: [0., 0., -1.],
};

impl Cylinder {
    /// Create a new cylinder.
    /// `u` is the number of points across the radius.
    pub fn new(u: usize) -> Self {
        assert!(u > 1);
        Cylinder {
            u: 0,
            h: -1,
            sub_u: u,
            sub_h: 1,
        }
    }

    /// Create a new subdivided cylinder.
    /// `u` is the number of points across the radius.
    /// `h` is the number of segments across the height.
    pub fn subdivide(u: usize, h: usize) -> Self {
        assert!(u > 1 && h > 0);
        Cylinder {
            u: 0,
            h: -1,
            sub_u: u,
            sub_h: h as isize,
        }
    }

    fn vert(&self, u: usize, h: isize) -> Vertex {
        debug_assert!(u <= self.sub_u);
        let a = (u as f32 / self.sub_u as f32) * PI * 2.;
        let n = [a.cos(), a.sin(), 0.];
        let (hc, normal) = if h < 0 {
            debug_assert_eq!(h, -1);
            (0, [0., 0., -1.])
        } else if h > self.sub_h {
            debug_assert_eq!(h, self.sub_h + 1);
            (self.sub_h, [0., 0., 1.])
        } else {
            (h, n)
        };
        let z = (hc as f32 / self.sub_h as f32) * 2. - 1.;
        Vertex {
            pos: [n[0], n[1], z],
            normal,
        }
    }
}

impl Iterator for Cylinder {
    type Item = Polygon<Vertex>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        let n = self.sub_u * (1 + self.sub_h - self.h) as usize - self.u;
        (n, Some(n))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if self.u == self.sub_u {
            if self.h >= self.sub_h {
                return None;
            }
            self.u = 0;
            self.h += 1;
        }

        let u = self.u;
        self.u += 1;
        // mathematically, reaching `u + 1 == sub_u` should trivially resolve,
        // because sin(2pi) == sin(0), but rounding errors go in the way.
        let u1 = self.u % self.sub_u;

        let x = self.vert(u, self.h);
        let y = self.vert(u1, self.h);

        Some(if self.h < 0 {
            Polygon::PolyTri(Triangle::new(x, BOT, y))
        } else if self.h == self.sub_h {
            Polygon::PolyTri(Triangle::new(x, y, TOP))
        } else {
            let z = self.vert(u1, self.h + 1);
            let w = self.vert(u, self.h + 1);
            Polygon::PolyQuad(Quad::new(x, y, z, w))
        })
    }
}

impl SharedVertex<Vertex> for Cylinder {
    fn shared_vertex(&self, idx: usize) -> Vertex {
        if idx == 0 {
            BOT
        } else if idx == self.shared_vertex_count() - 1 {
            TOP
        } else {
            // skip the bottom center
            let idx = idx - 1;
            let u = idx % self.sub_u;
            let h = (idx / self.sub_u) as isize - 1;
            self.vert(u, h)
        }
    }

    fn shared_vertex_count(&self) -> usize {
        (3 + self.sub_h) as usize * self.sub_u + 2
    }
}

impl IndexedPolygon<Polygon<usize>> for Cylinder {
    fn indexed_polygon(&self, idx: usize) -> Polygon<usize> {
        let u = idx % self.sub_u;
        let u1 = (idx + 1) % self.sub_u;
        let h = (idx / self.sub_u) as isize - 1;
        let base = 1 + idx - u;
        if h < 0 {
            let start = 0;
            Polygon::PolyTri(Triangle::new(base + u, start, base + u1))
        } else if h == self.sub_h {
            // We need to to select the next vertex loop over, which
            // has the correct normals.
            let base = base + self.sub_u;
            let end = self.shared_vertex_count() - 1;
            Polygon::PolyTri(Triangle::new(base + u, base + u1, end))
        } else {
            Polygon::PolyQuad(Quad::new(base + u,
                                        base + u1,
                                        base + u1 + self.sub_u,
                                        base + u + self.sub_u))
        }
    }

    fn indexed_polygon_count(&self) -> usize {
        (2 + self.sub_h) as usize * self.sub_u
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::fmt;
use std::cmp;
use std::collections::HashSet;

pub use self::rand::distributions::Range;
use self::rand::SeedableRng;
use self::rand::distributions::IndependentSample;

use genetic::fitness::HasFitness;
use genetic::mutation::Mutation;

use genetic::helpers::SimpleStepRange;

// Individual Stuff
#[derive(Debug)]
#[derive(Clone)]
pub struct Individual<T> {
    pub genome: Vec<T>,
}

impl<T> Individual<T> {
    pub fn new(size: usize, range: &Range<T>) -> Individual<T>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut genome: Vec<T> = Vec::new();
        let mut rng = rand::thread_rng();

        for _ in 0..size {
            let value = range.ind_sample(&mut rng);
            genome.push(value);
        }

        Individual::<T> { genome: genome }
    }
}

// Population Stuff
pub struct Population<T> {
    pub individuals: Vec<Individual<T>>,
    pub fitnesses: Vec<f32>,
    pub best_fitness_in_generation: Vec<f32>,
    pub average_fitness_in_generation: Vec<f32>,
    genome_length: usize,
    crossover_probability: f32,
    mutation_probability: f32,
    has_elitism: bool,
    range: Range<T>,

    fitness_function: fn(&Vec<T>) -> f32,
    crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
    mutation_function: fn(&mut Vec<T>, f32),
}

impl<T> Population<T>
    where T: Copy
{
    pub fn new(size: usize,
               genome_size: usize,
               crossover_probability: f32,
               mutation_probability: f32,
               range: Range<T>,
               has_elitism: bool,
               fitness_function: fn(&Vec<T>) -> f32,
               crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
               mutation_function: fn(&mut Vec<T>, f32))
               -> Population<T>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut individuals: Vec<Individual<T>> = Vec::new();
        let mut fitnesses: Vec<f32> = Vec::new();

        for i in 0..size {
            individuals.push(Individual::<T>::new(genome_size, &range));
            fitnesses.push(individuals[i].genome.fitness(&fitness_function));
        }

        Population::<T> {
            individuals: individuals,
            fitnesses: fitnesses,
            best_fitness_in_generation: Vec::<f32>::new(),
            average_fitness_in_generation: Vec::<f32>::new(),
            range: range,
            crossover_probability: crossover_probability,
            mutation_probability: mutation_probability,
            genome_length: genome_size,
            has_elitism: has_elitism,

            fitness_function: fitness_function,
            crossover_function: crossover_function,
            mutation_function: mutation_function,
        }
    }

    pub fn iterate_generation(&mut self) {
        let fittest_index = self.get_fittest_individual();
        let fittest_individual = self.individuals[fittest_index].clone();
        let fittest_fitness = self.fitnesses[fittest_index];

        let mut new_individuals = self.individuals.clone();
        for _ in SimpleStepRange(0, self.individuals.len(), 2) {
            if rand::random::<f32>() > self.crossover_probability {
                continue;
            }

            let dad_index = self.select_fit_individual();
            let mom_index = self.select_fit_individual_except(dad_index);

            //println!("dad: {}, mom: {}", dad_index, mom_index);
            let (boy_genome, girl_genome) = self.crossover(dad_index, mom_index);
            let (worst_index, second_worst_index) = self.get_weakest_couple();
            new_individuals[worst_index].genome.clone_from(&boy_genome);
            new_individuals[second_worst_index].genome.clone_from(&girl_genome);
        }
        self.individuals.clone_from(&new_individuals);

        for individual in &mut self.individuals {
            individual.genome.mutate(&self.mutation_function, self.mutation_probability);
        }

        self.compute_fitnesses();

        // Save average and best fitness in this generation
        {
            let best_fitness = 0.0;
            let mut sum_fitnesses = 0.0;
            for i in 0..self.fitnesses.len() {
                sum_fitnesses += self.fitnesses[i];
                if self.fitnesses[i] > best_fitness {
                    best_fitness = self.fitnesses[i];
                }
            }
            let avg_fitness = sum_fitnesses / (self.fitnesses.len() as f32);

            self.average_fitness_in_generation.push(avg_fitness);
            self.best_fitness_in_generation.push(best_fitness);
        }

    }

    fn select_fit_individual(&self) -> usize {
        self.roulette()
    }

    fn select_fit_individual_except(&self, dad_index: usize) -> usize {
        let mut mom_index: usize;

        loop {
            mom_index = self.roulette();

            if mom_index != dad_index {
                break;
            }
        }
        mom_index
    }

    fn get_fittest_individual(&self) -> usize {
        let mut fittest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] > self.fitnesses[fittest_index] {
                fittest_index = i;
            }
        }
        fittest_index
    }

    fn get_weakest_couple(&self) -> (usize, usize) {
        let mut weakest_index = 0;
        let mut second_weakest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] < self.fitnesses[weakest_index] {
                second_weakest_index = weakest_index;
                weakest_index = i;
            }
        }
        (weakest_index, second_weakest_index)
    }

    fn compute_fitnesses(&mut self) {
        for i in 0..self.individuals.len() {
            self.fitnesses[i] = self.individuals[i].genome.fitness(&self.fitness_function);
        }

        if self.has_elitism {
            let (weakest_index, _) = self.get_weakest_couple();
            self.individuals[weakest_index] = fittest_individual.clone();
            self.fitnesses[weakest_index] = fittest_fitness;
        }
    }

    fn crossover(&mut self, index_dad: usize, index_mom: usize) -> (Vec<T>, Vec<T>) {
        let max_index = cmp::max(index_dad, index_mom);
        let min_index = cmp::min(index_dad, index_mom);

        let (split_left, split_right) = self.individuals.split_at_mut(max_index);
        let (dad, mom) = (&mut split_left[min_index], &mut split_right[0]);

        let (boy_genome, girl_genome) = (self.crossover_function)(&dad.genome, &mom.genome);

        (boy_genome, girl_genome)
    }

    fn tournament(&self, k: usize) -> usize {
        let range = Range::new(0, self.individuals.len());

        let mut biggest: usize = 0;
        let mut processed_candidates = HashSet::<usize>::new();
        let mut rng = rand::thread_rng();

        while processed_candidates.len() < k {
            let picked = range.ind_sample(&mut rng);

            if processed_candidates.contains(&picked) {
                continue;
            }

            processed_candidates.insert(picked);

            if self.fitnesses[picked] > self.fitnesses[biggest] {
                biggest = picked;
            }
        }

        biggest
    }

    fn roulette(&self) -> usize {
        let chance = rand::random::<f32>();
        let sum = self.fitnesses.iter().fold(0.0, |acc, &x| acc + x);

        let mut winner: usize = 0;
        let mut last_probability = 0.0;
        for i in 0..self.fitnesses.len() {
            let fitness = self.fitnesses[i];
            let probability = fitness / sum + last_probability;

            if chance < probability {
                winner = i;
                break;
            }

            last_probability = probability;
        }
        winner
    }
}
<commit_msg>Keeps track of best individual, not just fitness<commit_after>extern crate rand;

use std::fmt;
use std::cmp;
use std::collections::HashSet;

pub use self::rand::distributions::Range;
use self::rand::SeedableRng;
use self::rand::distributions::IndependentSample;

use genetic::fitness::HasFitness;
use genetic::mutation::Mutation;

use genetic::helpers::SimpleStepRange;

// Individual Stuff
#[derive(Debug)]
#[derive(Clone)]
pub struct Individual<T> {
    pub genome: Vec<T>,
}

impl<T> Individual<T> {
    pub fn new(size: usize, range: &Range<T>) -> Individual<T>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut genome: Vec<T> = Vec::new();
        let mut rng = rand::thread_rng();

        for _ in 0..size {
            let value = range.ind_sample(&mut rng);
            genome.push(value);
        }

        Individual::<T> { genome: genome }
    }
}

// Population Stuff
pub struct Population<T> {
    pub individuals: Vec<Individual<T>>,
    pub fitnesses: Vec<f32>,
    pub best_individual_in_generation: Vec<Individual<T>>,
    pub best_fitness_in_generation: Vec<f32>,
    pub average_fitness_in_generation: Vec<f32>,
    genome_length: usize,
    crossover_probability: f32,
    mutation_probability: f32,
    has_elitism: bool,
    range: Range<T>,

    fitness_function: fn(&Vec<T>) -> f32,
    crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
    mutation_function: fn(&mut Vec<T>, f32),
}

impl<T> Population<T>
    where T: Copy
{
    pub fn new(size: usize,
               genome_size: usize,
               crossover_probability: f32,
               mutation_probability: f32,
               range: Range<T>,
               has_elitism: bool,
               fitness_function: fn(&Vec<T>) -> f32,
               crossover_function: fn(&Vec<T>, &Vec<T>) -> (Vec<T>, Vec<T>),
               mutation_function: fn(&mut Vec<T>, f32))
               -> Population<T>
        where T: rand::Rand + rand::distributions::range::SampleRange
    {
        let mut individuals: Vec<Individual<T>> = Vec::new();
        let mut fitnesses: Vec<f32> = Vec::new();

        for i in 0..size {
            individuals.push(Individual::<T>::new(genome_size, &range));
            fitnesses.push(individuals[i].genome.fitness(&fitness_function));
        }

        Population::<T> {
            individuals: individuals,
            fitnesses: fitnesses,
            best_individual_in_generation: Vec::<Individual<T>>::new(),
            best_fitness_in_generation: Vec::<f32>::new(),
            average_fitness_in_generation: Vec::<f32>::new(),
            range: range,
            crossover_probability: crossover_probability,
            mutation_probability: mutation_probability,
            genome_length: genome_size,
            has_elitism: has_elitism,

            fitness_function: fitness_function,
            crossover_function: crossover_function,
            mutation_function: mutation_function,
        }
    }

    pub fn iterate_generation(&mut self) {
        let fittest_index = self.get_fittest_individual();
        let fittest_individual = self.individuals[fittest_index].clone();
        let fittest_fitness = self.fitnesses[fittest_index];

        let mut new_individuals = self.individuals.clone();
        for _ in SimpleStepRange(0, self.individuals.len(), 2) {
            if rand::random::<f32>() > self.crossover_probability {
                continue;
            }

            let dad_index = self.select_fit_individual();
            let mom_index = self.select_fit_individual_except(dad_index);

            //println!("dad: {}, mom: {}", dad_index, mom_index);
            let (boy_genome, girl_genome) = self.crossover(dad_index, mom_index);
            let (worst_index, second_worst_index) = self.get_weakest_couple();
            new_individuals[worst_index].genome.clone_from(&boy_genome);
            new_individuals[second_worst_index].genome.clone_from(&girl_genome);
        }
        self.individuals.clone_from(&new_individuals);

        for individual in &mut self.individuals {
            individual.genome.mutate(&self.mutation_function, self.mutation_probability);
        }

        self.compute_fitnesses();
        if self.has_elitism {
            let (weakest_index, _) = self.get_weakest_couple();
            self.individuals[weakest_index] = fittest_individual.clone();
            self.fitnesses[weakest_index] = fittest_fitness;
        }

        // Save average and best fitness in this generation
        {
            let mut best_fitness = 0.0;
            let mut best_individual = self.individuals[0].clone();
            let mut sum_fitnesses = 0.0;
            for i in 0..self.fitnesses.len() {
                sum_fitnesses += self.fitnesses[i];
                if self.fitnesses[i] > best_fitness {
                    best_fitness = self.fitnesses[i];
                    best_individual = self.individuals[i].clone();
                }
            }
            let avg_fitness = sum_fitnesses / (self.fitnesses.len() as f32);

            self.average_fitness_in_generation.push(avg_fitness);
            self.best_individual_in_generation.push(best_individual);
            self.best_fitness_in_generation.push(best_fitness);
        }

    }

    fn select_fit_individual(&self) -> usize {
        self.roulette()
    }

    fn select_fit_individual_except(&self, dad_index: usize) -> usize {
        let mut mom_index: usize;

        loop {
            mom_index = self.roulette();

            if mom_index != dad_index {
                break;
            }
        }
        mom_index
    }

    fn get_fittest_individual(&self) -> usize {
        let mut fittest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] > self.fitnesses[fittest_index] {
                fittest_index = i;
            }
        }
        fittest_index
    }

    fn get_weakest_couple(&self) -> (usize, usize) {
        let mut weakest_index = 0;
        let mut second_weakest_index = 0;

        for i in 1..self.individuals.len() {
            if self.fitnesses[i] < self.fitnesses[weakest_index] {
                second_weakest_index = weakest_index;
                weakest_index = i;
            }
        }
        (weakest_index, second_weakest_index)
    }

    fn compute_fitnesses(&mut self) {
        for i in 0..self.individuals.len() {
            self.fitnesses[i] = self.individuals[i].genome.fitness(&self.fitness_function);
        }
    }

    fn crossover(&mut self, index_dad: usize, index_mom: usize) -> (Vec<T>, Vec<T>) {
        let max_index = cmp::max(index_dad, index_mom);
        let min_index = cmp::min(index_dad, index_mom);

        let (split_left, split_right) = self.individuals.split_at_mut(max_index);
        let (dad, mom) = (&mut split_left[min_index], &mut split_right[0]);

        let (boy_genome, girl_genome) = (self.crossover_function)(&dad.genome, &mom.genome);

        (boy_genome, girl_genome)
    }

    fn tournament(&self, k: usize) -> usize {
        let range = Range::new(0, self.individuals.len());

        let mut biggest: usize = 0;
        let mut processed_candidates = HashSet::<usize>::new();
        let mut rng = rand::thread_rng();

        while processed_candidates.len() < k {
            let picked = range.ind_sample(&mut rng);

            if processed_candidates.contains(&picked) {
                continue;
            }

            processed_candidates.insert(picked);

            if self.fitnesses[picked] > self.fitnesses[biggest] {
                biggest = picked;
            }
        }

        biggest
    }

    fn roulette(&self) -> usize {
        let chance = rand::random::<f32>();
        let sum = self.fitnesses.iter().fold(0.0, |acc, &x| acc + x);

        let mut winner: usize = 0;
        let mut last_probability = 0.0;
        for i in 0..self.fitnesses.len() {
            let fitness = self.fitnesses[i];
            let probability = fitness / sum + last_probability;

            if chance < probability {
                winner = i;
                break;
            }

            last_probability = probability;
        }
        winner
    }
}
<|endoftext|>


<commit_before>extern crate debugserver_types;
extern crate env_logger;
extern crate futures;
extern crate jsonrpc_core;
extern crate serde;
extern crate serde_json;
extern crate log;

extern crate gluon_language_server;
extern crate gluon;

use std::error::Error as StdError;
use std::fs::File;
use std::io::{BufReader, Read};
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Barrier, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::thread::spawn;
use std::collections::{HashMap, HashSet};

use futures::{Async, BoxFuture, Future, IntoFuture};

use jsonrpc_core::IoHandler;

use serde_json::Value;

use debugserver_types::*;

use gluon::base::pos::Line;
use gluon::vm::api::{OpaqueValue, Hole};
use gluon::vm::thread::{RootedThread, ThreadInternal, LINE_FLAG};
use gluon::{Compiler, filename_to_module};

use gluon_language_server::rpc::{LanguageServerCommand, ServerCommand, ServerError, main_loop,
                                 write_message};

pub struct InitializeHandler {
    debugger: Arc<Debugger>,
}

impl LanguageServerCommand<InitializeRequestArguments> for InitializeHandler {
    type Output = Option<Capabilities>;
    type Error = ();
    fn execute(&self,
               args: InitializeRequestArguments)
               -> BoxFuture<Option<Capabilities>, ServerError<Self::Error>> {
        self.debugger
            .lines_start_at_1
            .store(args.lines_start_at_1.unwrap_or(true), Ordering::Release);

        self.debugger.send_event(InitializedEvent {
            body: None,
            event: "initialized".into(),
            seq: self.debugger.seq(),
            type_: "event".into(),
        });

        Ok(Some(Capabilities {
                supports_configuration_done_request: Some(true),
                ..Capabilities::default()
            }))
            .into_future()
            .boxed()
    }
}

pub struct LaunchHandler {
    debugger: Arc<Debugger>,
    thread: RootedThread,
    stream: Arc<TcpStream>,
    seq: Arc<AtomicUsize>,
}

impl LanguageServerCommand<Value> for LaunchHandler {
    type Output = Option<Value>;
    type Error = ();
    fn execute(&self, args: Value) -> BoxFuture<Option<Value>, ServerError<()>> {
        self.execute_launch(args).into_future().boxed()
    }
}

impl LaunchHandler {
    fn execute_launch(&self, args: Value) -> Result<Option<Value>, ServerError<()>> {
        let program = args.get("program")
            .and_then(|s| s.as_str())
            .ok_or_else(|| {
                ServerError {
                    message: "No program argument found".into(),
                    data: None,
                }
            })?;
        let module = filename_to_module(program);
        let expr = {
            let mut file = File::open(program).map_err(|_| {
                    ServerError {
                        message: format!("Program does not exit: `{}`", program),
                        data: None,
                    }
                })?;
            let mut expr = String::new();
            file.read_to_string(&mut expr).expect("Could not read from file");
            expr
        };

        let debugger = self.debugger.clone();
        self.thread.context().set_hook(Some(Box::new(move |_, debug_info| {
            let stack_info = debug_info.stack_info(0).unwrap();
            if let Some(line) = stack_info.line() {
                if debugger.should_break(stack_info.source_name(), line) {
                    debugger.send_event(StoppedEvent {
                        body: StoppedEventBody {
                            all_threads_stopped: Some(true),
                            reason: "breakpoint".into(),
                            text: None,
                            thread_id: Some(1),
                        },
                        event: "stopped".to_string(),
                        seq: debugger.seq(),
                        type_: "event".to_string(),
                    });

                    debugger.continue_barrier.wait();
                }
            }
            Ok(Async::Ready(()))
        })));
        self.thread.context().set_hook_mask(LINE_FLAG);

        let debugger = self.debugger.clone();
        let thread = self.thread.clone();
        let seq = self.seq.clone();
        let stream = self.stream.clone();
        spawn(move || {
            // Wait for the initialization to finish
            debugger.continue_barrier.wait();

            let _result = Compiler::new()
                .implicit_prelude(false)
                .run_expr::<OpaqueValue<RootedThread, Hole>>(&thread, &module, &expr);
            let seq = seq.fetch_add(1, Ordering::SeqCst) as i64;
            let terminated = TerminatedEvent {
                body: None,
                event: "terminated".into(),
                seq: seq,
                type_: "event".into(),
            };
            write_message(&*stream, &terminated).unwrap();
        });
        Ok(None)
    }
}

pub struct DisconnectHandler {
    exit_token: Arc<AtomicBool>,
}

impl LanguageServerCommand<DisconnectArguments> for DisconnectHandler {
    type Output = Option<Value>;
    type Error = ();
    fn execute(&self, _args: Value) -> BoxFuture<Option<Value>, ServerError<()>> {
        self.exit_token.store(true, Ordering::SeqCst);
        Ok(None).into_future().boxed()
    }
}

// Translate debug server messages into jsonrpc-2.0
fn translate_request(message: String) -> Result<String, Box<StdError>> {
    use serde_json::Value;
    let mut data: Value = try!(serde_json::from_str(&message));
    if data.is_object() {
        let data = data.as_object_mut().unwrap();
        let command = data.get("command").and_then(|c| c.as_str()).expect("command").to_string();
        let seq = data.get("seq")
            .and_then(|c| {
                c.as_str()
                    .map(|s| Value::String(s.to_string()))
                    .or_else(|| c.as_i64().map(Value::from))
            })
            .expect("seq");
        let arguments = data.remove("arguments").unwrap_or(Value::Object(Default::default()));
        let map = vec![("method".to_string(), Value::String(command)),
                       ("id".to_string(), seq),
                       ("params".to_string(), arguments),
                       ("jsonrpc".to_owned(), Value::String("2.0".to_string()))]
            .into_iter()
            .collect();
        return Ok(try!(serde_json::to_string(&Value::Object(map))));
    }
    Ok(message)
}

fn translate_response(debugger: &Debugger, message: String) -> Result<String, Box<StdError>> {
    use serde_json::Value;
    let mut data: Value = try!(serde_json::from_str(&message));
    if data.is_object() {
        let data = data.as_object_mut().unwrap();
        let seq = data.get("id")
            .and_then(|c| {
                c.as_str()
                    .map(|s| Value::String(s.to_string()))
                    .or_else(|| c.as_i64().map(Value::from))
            })
            .expect("id");
        let result = data.remove("result");
        let error = data.remove("error");

        let mut map = vec![("success".to_string(), Value::Bool(result.is_some())),
                           ("request_seq".to_string(), seq),
                           ("seq".to_string(), Value::from(debugger.seq())),
                           ("type".to_owned(), Value::String("response".to_string()))];

        if let Some(result) = result {
            map.push(("body".to_string(), result));
        }
        if let Some(mut error) = error {
            map.push(("message".to_string(),
                      error.as_object_mut().unwrap().remove("message").expect("error message")));
        }

        let map = map.into_iter().collect();
        return Ok(try!(serde_json::to_string(&Value::Object(map))));
    }
    Ok(message)
}

pub struct Debugger {
    stream: Arc<TcpStream>,
    breakpoints: Mutex<HashMap<String, HashSet<Line>>>,
    continue_barrier: Barrier,
    seq: Arc<AtomicUsize>,
    lines_start_at_1: AtomicBool,
    // When continuing the response must be sent before actually conituing execution otherwise the `stopped`
    // action could be received by visual code before the continue response which causes it to not recognize
    // the stopped action
    do_continue: AtomicBool,
}

impl Debugger {
    fn seq(&self) -> i64 {
        self.seq.fetch_add(1, Ordering::SeqCst) as i64
    }

    fn should_break(&self, source_name: &str, line: Line) -> bool {
        let breakpoints = self.breakpoints.lock().expect("breakpoints mutex is poisoned");
        breakpoints.get(source_name)
            .map_or(false, |lines| lines.contains(&line))
    }

    fn line(&self, line: i64) -> Line {
        Line::from((line as usize)
            .saturating_sub(self.lines_start_at_1.load(Ordering::Acquire) as usize))
    }

    fn send_event<T>(&self, value: T)
        where T: serde::Serialize,
    {
        write_message(&*self.stream, &value).unwrap();
    }
}

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

    let listener = TcpListener::bind("127.0.0.1:4711").unwrap();
    for stream in listener.incoming() {
        let stream = Arc::new(stream.unwrap());

        let exit_token = Arc::new(AtomicBool::new(false));
        let seq = Arc::new(AtomicUsize::new(1));

        let thread = gluon::new_vm();

        let debugger = Arc::new(Debugger {
            stream: stream.clone(),
            breakpoints: Mutex::new(HashMap::new()),
            continue_barrier: Barrier::new(2),
            seq: seq.clone(),
            lines_start_at_1: AtomicBool::new(true),
            do_continue: AtomicBool::new(false),
        });

        let mut io = IoHandler::new();
        io.add_async_method("initialize",
                            ServerCommand::new(InitializeHandler { debugger: debugger.clone() }));

        {
            let debugger = debugger.clone();
            let configuration_done =
                move |_: ConfigurationDoneArguments| -> BoxFuture<(), ServerError<()>> {
                    // Notify the launched thread that it can start executing
                    debugger.continue_barrier.wait();
                    Ok(()).into_future().boxed()
                };
            io.add_async_method("configurationDone", ServerCommand::new(configuration_done));
        }

        io.add_async_method("launch",
                            ServerCommand::new(LaunchHandler {
                                debugger: debugger.clone(),
                                thread: thread,
                                stream: stream.clone(),
                                seq: seq.clone(),
                            }));
        io.add_async_method("disconnect",
                            ServerCommand::new(DisconnectHandler {
                                exit_token: exit_token.clone(),
                            }));
        {
            let debugger = debugger.clone();
            let set_break = move |args: SetBreakpointsArguments| -> BoxFuture<_, ServerError<()>> {
                let mut breakpoint_map = debugger.breakpoints.lock().unwrap();
                let breakpoints = args.breakpoints
                    .iter()
                    .flat_map(|bs| bs.iter().map(|breakpoint| debugger.line(breakpoint.line)))
                    .collect();
                if let Some(path) = args.source.path {
                    breakpoint_map.insert(filename_to_module(path.trim_right_matches(".glu")),
                                          breakpoints);
                }

                Ok(SetBreakpointsResponseBody {
                        breakpoints: args.breakpoints
                            .into_iter()
                            .flat_map(|bs| bs)
                            .map(|breakpoint| {
                                Breakpoint {
                                    column: None,
                                    end_column: None,
                                    end_line: None,
                                    id: None,
                                    line: Some(breakpoint.line),
                                    message: None,
                                    source: None,
                                    verified: true,
                                }
                            })
                            .collect(),
                    })
                    .into_future()
                    .boxed()
            };

            io.add_async_method("setBreakpoints", ServerCommand::new(set_break));
        }

        let threads = move |_: Value| -> BoxFuture<ThreadsResponseBody, ServerError<()>> {
            Ok(ThreadsResponseBody {
                    threads: vec![Thread {
                                      id: 1,
                                      name: "main".to_string(),
                                  }],
                })
                .into_future()
                .boxed()
        };

        io.add_async_method("threads", ServerCommand::new(threads));

        let stack_trace = move |_: StackTraceArguments| -> BoxFuture<_, ServerError<()>> {
            Ok(StackTraceResponseBody {
                    stack_frames: vec![StackFrame {
                                           column: 0,
                                           end_column: None,
                                           end_line: None,
                                           id: 0,
                                           line: 0,
                                           module_id: None,
                                           name: "main".to_string(),
                                           source: None,
                                       }],
                    total_frames: Some(1),
                })
                .into_future()
                .boxed()
        };
        io.add_async_method("stackTrace", ServerCommand::new(stack_trace));

        let scopes = move |_: ScopesArguments| -> BoxFuture<_, ServerError<()>> {
            Ok(ScopesResponseBody {
                    scopes: vec![Scope {
                                     column: None,
                                     end_column: None,
                                     end_line: None,
                                     expensive: false,
                                     indexed_variables: None,
                                     line: None,
                                     name: "Locals".to_string(),
                                     named_variables: None,
                                     source: Some(Source {
                                         name: Some("main".to_string()),
                                         ..Source::default()
                                     }),
                                     variables_reference: 0,
                                 }],
                })
                .into_future()
                .boxed()
        };
        io.add_async_method("scopes", ServerCommand::new(scopes));

        {
            let debugger = debugger.clone();
            let cont =
                move |_: ContinueArguments| -> BoxFuture<ContinueResponseBody, ServerError<()>> {
                    debugger.do_continue.store(true, Ordering::Release);
                    Ok(ContinueResponseBody { all_threads_continued: Some(true) })
                        .into_future()
                        .boxed()
                };
            io.add_async_method("continue", ServerCommand::new(cont));
        }
        spawn(move || {
            let read = BufReader::new(&*stream);
            let post_request_action = || {
                if debugger.do_continue.load(Ordering::Acquire) {
                    debugger.do_continue.store(false, Ordering::Release);
                    debugger.continue_barrier.wait();
                }
                Ok(())
            };
            main_loop(read,
                      &*stream,
                      &io,
                      exit_token,
                      post_request_action,
                      translate_request,
                      |body| translate_response(&debugger, body))
                .unwrap()
        });
    }
}
<commit_msg>fix: Resolve the file in which the debugger stopped in correctly<commit_after>extern crate debugserver_types;
extern crate env_logger;
extern crate futures;
extern crate jsonrpc_core;
extern crate serde;
extern crate serde_json;
extern crate log;

extern crate gluon_language_server;
extern crate gluon;

use std::error::Error as StdError;
use std::fs::File;
use std::io::{BufReader, Read};
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Barrier, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::thread::spawn;
use std::collections::{HashMap, HashSet};

use futures::{Async, BoxFuture, Future, IntoFuture};

use jsonrpc_core::IoHandler;

use serde_json::Value;

use debugserver_types::*;

use gluon::base::pos::Line;
use gluon::vm::api::{OpaqueValue, Hole};
use gluon::vm::thread::{DebugInfo, RootedThread, ThreadInternal, LINE_FLAG};
use gluon::{Compiler, filename_to_module};

use gluon_language_server::rpc::{LanguageServerCommand, ServerCommand, ServerError, main_loop,
                                 write_message};

pub struct InitializeHandler {
    debugger: Arc<Debugger>,
}

impl LanguageServerCommand<InitializeRequestArguments> for InitializeHandler {
    type Output = Option<Capabilities>;
    type Error = ();
    fn execute(&self,
               args: InitializeRequestArguments)
               -> BoxFuture<Option<Capabilities>, ServerError<Self::Error>> {
        self.debugger
            .lines_start_at_1
            .store(args.lines_start_at_1.unwrap_or(true), Ordering::Release);

        self.debugger.send_event(InitializedEvent {
            body: None,
            event: "initialized".into(),
            seq: self.debugger.seq(),
            type_: "event".into(),
        });

        Ok(Some(Capabilities {
                supports_configuration_done_request: Some(true),
                ..Capabilities::default()
            }))
            .into_future()
            .boxed()
    }
}

pub struct LaunchHandler {
    debugger: Arc<Debugger>,
    thread: RootedThread,
    stream: Arc<TcpStream>,
    seq: Arc<AtomicUsize>,
}

impl LanguageServerCommand<Value> for LaunchHandler {
    type Output = Option<Value>;
    type Error = ();
    fn execute(&self, args: Value) -> BoxFuture<Option<Value>, ServerError<()>> {
        self.execute_launch(args).into_future().boxed()
    }
}

impl LaunchHandler {
    fn execute_launch(&self, args: Value) -> Result<Option<Value>, ServerError<()>> {
        let program = args.get("program")
            .and_then(|s| s.as_str())
            .ok_or_else(|| {
                ServerError {
                    message: "No program argument found".into(),
                    data: None,
                }
            })?;
        let module = filename_to_module(program);
        let expr = {
            let mut file = File::open(program).map_err(|_| {
                    ServerError {
                        message: format!("Program does not exit: `{}`", program),
                        data: None,
                    }
                })?;
            let mut expr = String::new();
            file.read_to_string(&mut expr).expect("Could not read from file");
            expr
        };

        let debugger = self.debugger.clone();
        self.thread.context().set_hook(Some(Box::new(move |_, debug_info| {
            let stack_info = debug_info.stack_info(0).unwrap();
            if let Some(line) = stack_info.line() {
                if debugger.should_break(stack_info.source_name(), line) {
                    debugger.store_stack_trace(&debug_info);

                    debugger.send_event(StoppedEvent {
                        body: StoppedEventBody {
                            all_threads_stopped: Some(true),
                            reason: "breakpoint".into(),
                            text: None,
                            thread_id: Some(1),
                        },
                        event: "stopped".to_string(),
                        seq: debugger.seq(),
                        type_: "event".to_string(),
                    });

                    debugger.continue_barrier.wait();
                }
            }
            Ok(Async::Ready(()))
        })));
        self.thread.context().set_hook_mask(LINE_FLAG);

        let debugger = self.debugger.clone();
        let thread = self.thread.clone();
        let seq = self.seq.clone();
        let stream = self.stream.clone();
        spawn(move || {
            // Wait for the initialization to finish
            debugger.continue_barrier.wait();

            let _result = Compiler::new()
                .implicit_prelude(false)
                .run_expr::<OpaqueValue<RootedThread, Hole>>(&thread, &module, &expr);
            let seq = seq.fetch_add(1, Ordering::SeqCst) as i64;
            let terminated = TerminatedEvent {
                body: None,
                event: "terminated".into(),
                seq: seq,
                type_: "event".into(),
            };
            write_message(&*stream, &terminated).unwrap();
        });
        Ok(None)
    }
}

pub struct DisconnectHandler {
    exit_token: Arc<AtomicBool>,
}

impl LanguageServerCommand<DisconnectArguments> for DisconnectHandler {
    type Output = Option<Value>;
    type Error = ();
    fn execute(&self, _args: Value) -> BoxFuture<Option<Value>, ServerError<()>> {
        self.exit_token.store(true, Ordering::SeqCst);
        Ok(None).into_future().boxed()
    }
}

// Translate debug server messages into jsonrpc-2.0
fn translate_request(message: String) -> Result<String, Box<StdError>> {
    use serde_json::Value;
    let mut data: Value = try!(serde_json::from_str(&message));
    if data.is_object() {
        let data = data.as_object_mut().unwrap();
        let command = data.get("command").and_then(|c| c.as_str()).expect("command").to_string();
        let seq = data.get("seq")
            .and_then(|c| {
                c.as_str()
                    .map(|s| Value::String(s.to_string()))
                    .or_else(|| c.as_i64().map(Value::from))
            })
            .expect("seq");
        let arguments = data.remove("arguments").unwrap_or(Value::Object(Default::default()));
        let map = vec![("method".to_string(), Value::String(command)),
                       ("id".to_string(), seq),
                       ("params".to_string(), arguments),
                       ("jsonrpc".to_owned(), Value::String("2.0".to_string()))]
            .into_iter()
            .collect();
        return Ok(try!(serde_json::to_string(&Value::Object(map))));
    }
    Ok(message)
}

fn translate_response(debugger: &Debugger, message: String) -> Result<String, Box<StdError>> {
    use serde_json::Value;
    let mut data: Value = try!(serde_json::from_str(&message));
    if data.is_object() {
        let data = data.as_object_mut().unwrap();
        let seq = data.get("id")
            .and_then(|c| {
                c.as_str()
                    .map(|s| Value::String(s.to_string()))
                    .or_else(|| c.as_i64().map(Value::from))
            })
            .expect("id");
        let result = data.remove("result");
        let error = data.remove("error");

        let mut map = vec![("success".to_string(), Value::Bool(result.is_some())),
                           ("request_seq".to_string(), seq),
                           ("seq".to_string(), Value::from(debugger.seq())),
                           ("type".to_owned(), Value::String("response".to_string()))];

        if let Some(result) = result {
            map.push(("body".to_string(), result));
        }
        if let Some(mut error) = error {
            map.push(("message".to_string(),
                      error.as_object_mut().unwrap().remove("message").expect("error message")));
        }

        let map = map.into_iter().collect();
        return Ok(try!(serde_json::to_string(&Value::Object(map))));
    }
    Ok(message)
}

struct SourceData {
    source: Option<Source>,
    breakpoints: HashSet<Line>,
}

struct Debugger {
    stream: Arc<TcpStream>,
    sources: Mutex<HashMap<String, SourceData>>,
    continue_barrier: Barrier,
    seq: Arc<AtomicUsize>,
    lines_start_at_1: AtomicBool,
    // When continuing the response must be sent before actually conituing execution otherwise the `stopped`
    // action could be received by visual code before the continue response which causes it to not recognize
    // the stopped action
    do_continue: AtomicBool,

    stack_trace: Mutex<Vec<StackFrame>>,
}

impl Debugger {
    fn seq(&self) -> i64 {
        self.seq.fetch_add(1, Ordering::SeqCst) as i64
    }

    fn should_break(&self, source_name: &str, line: Line) -> bool {
        let sources = self.sources.lock().expect("sources mutex is poisoned");
        sources.get(source_name)
            .map_or(false, |source| source.breakpoints.contains(&line))
    }

    fn line(&self, line: i64) -> Line {
        Line::from((line as usize)
            .saturating_sub(self.lines_start_at_1.load(Ordering::Acquire) as usize))
    }

    fn send_event<T>(&self, value: T)
        where T: serde::Serialize,
    {
        write_message(&*self.stream, &value).unwrap();
    }

    // Stores the stackstack trace so it can be returned in later requests
    fn store_stack_trace(&self, info: &DebugInfo) {
        let mut vec = self.stack_trace.lock().unwrap();
        vec.clear();
        let mut i = 0;

        let sources = self.sources.lock().unwrap();
        while let Some(stack_info) = info.stack_info(i) {
            vec.push(StackFrame {
                column: 0,
                end_column: None,
                end_line: None,
                id: 0,
                line: stack_info.line().map_or(0, |line| line.to_usize() as i64 + 1),
                module_id: None,
                name: "main".to_string(),
                source: sources.get(stack_info.source_name())
                    .and_then(|source| source.source.clone()),
            });
            i += 1;
        }
    }
}

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

    let listener = TcpListener::bind("127.0.0.1:4711").unwrap();
    for stream in listener.incoming() {
        let stream = Arc::new(stream.unwrap());

        let exit_token = Arc::new(AtomicBool::new(false));
        let seq = Arc::new(AtomicUsize::new(1));

        let thread = gluon::new_vm();

        let debugger = Arc::new(Debugger {
            stream: stream.clone(),
            sources: Mutex::new(HashMap::new()),
            continue_barrier: Barrier::new(2),
            seq: seq.clone(),
            lines_start_at_1: AtomicBool::new(true),
            do_continue: AtomicBool::new(false),
            stack_trace: Mutex::new(Vec::new()),
        });

        let mut io = IoHandler::new();
        io.add_async_method("initialize",
                            ServerCommand::new(InitializeHandler { debugger: debugger.clone() }));

        {
            let debugger = debugger.clone();
            let configuration_done =
                move |_: ConfigurationDoneArguments| -> BoxFuture<(), ServerError<()>> {
                    // Notify the launched thread that it can start executing
                    debugger.continue_barrier.wait();
                    Ok(()).into_future().boxed()
                };
            io.add_async_method("configurationDone", ServerCommand::new(configuration_done));
        }

        io.add_async_method("launch",
                            ServerCommand::new(LaunchHandler {
                                debugger: debugger.clone(),
                                thread: thread,
                                stream: stream.clone(),
                                seq: seq.clone(),
                            }));
        io.add_async_method("disconnect",
                            ServerCommand::new(DisconnectHandler {
                                exit_token: exit_token.clone(),
                            }));
        {
            let debugger = debugger.clone();
            let set_break = move |args: SetBreakpointsArguments| -> BoxFuture<_, ServerError<()>> {
                let breakpoints = args.breakpoints
                    .iter()
                    .flat_map(|bs| bs.iter().map(|breakpoint| debugger.line(breakpoint.line)))
                    .collect();

                let opt = args.source
                    .path
                    .as_ref()
                    .map(|path| filename_to_module(path.trim_right_matches(".glu")));
                if let Some(path) = opt {
                    let mut sources = debugger.sources.lock().unwrap();
                    sources.insert(path,
                                   SourceData {
                                       source: Some(args.source.clone()),
                                       breakpoints: breakpoints,
                                   });
                }

                Ok(SetBreakpointsResponseBody {
                        breakpoints: args.breakpoints
                            .into_iter()
                            .flat_map(|bs| bs)
                            .map(|breakpoint| {
                                Breakpoint {
                                    column: None,
                                    end_column: None,
                                    end_line: None,
                                    id: None,
                                    line: Some(breakpoint.line),
                                    message: None,
                                    source: None,
                                    verified: true,
                                }
                            })
                            .collect(),
                    })
                    .into_future()
                    .boxed()
            };

            io.add_async_method("setBreakpoints", ServerCommand::new(set_break));
        }

        let threads = move |_: Value| -> BoxFuture<ThreadsResponseBody, ServerError<()>> {
            Ok(ThreadsResponseBody {
                    threads: vec![Thread {
                                      id: 1,
                                      name: "main".to_string(),
                                  }],
                })
                .into_future()
                .boxed()
        };

        io.add_async_method("threads", ServerCommand::new(threads));

        {
            let debugger = debugger.clone();
            let stack_trace = move |_: StackTraceArguments| -> BoxFuture<_, ServerError<()>> {
                let stack_frames = (*debugger.stack_trace.lock().unwrap()).clone();
                Ok(StackTraceResponseBody {
                        total_frames: Some(stack_frames.len() as i64),
                        stack_frames: stack_frames,
                    })
                    .into_future()
                    .boxed()
            };
            io.add_async_method("stackTrace", ServerCommand::new(stack_trace));
        }

        let scopes = move |_: ScopesArguments| -> BoxFuture<_, ServerError<()>> {
            Ok(ScopesResponseBody {
                    scopes: vec![Scope {
                                     column: None,
                                     end_column: None,
                                     end_line: None,
                                     expensive: false,
                                     indexed_variables: None,
                                     line: None,
                                     name: "Locals".to_string(),
                                     named_variables: None,
                                     source: Some(Source {
                                         name: Some("main".to_string()),
                                         ..Source::default()
                                     }),
                                     variables_reference: 0,
                                 }],
                })
                .into_future()
                .boxed()
        };
        io.add_async_method("scopes", ServerCommand::new(scopes));

        {
            let debugger = debugger.clone();
            let cont =
                move |_: ContinueArguments| -> BoxFuture<ContinueResponseBody, ServerError<()>> {
                    debugger.do_continue.store(true, Ordering::Release);
                    Ok(ContinueResponseBody { all_threads_continued: Some(true) })
                        .into_future()
                        .boxed()
                };
            io.add_async_method("continue", ServerCommand::new(cont));
        }
        spawn(move || {
            let read = BufReader::new(&*stream);
            let post_request_action = || {
                if debugger.do_continue.load(Ordering::Acquire) {
                    debugger.do_continue.store(false, Ordering::Release);
                    debugger.continue_barrier.wait();
                }
                Ok(())
            };
            main_loop(read,
                      &*stream,
                      &io,
                      exit_token,
                      post_request_action,
                      translate_request,
                      |body| translate_response(&debugger, body))
                .unwrap()
        });
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Sanguk Park
 *
 * 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
 *
 *     https://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.
 */

use core::mem;
use core::str;

use crate::addr::*;
use crate::arch::*;
use crate::boot_params::*;
use crate::cpio::*;
use crate::cpu::*;
use crate::layout::*;
use crate::memiter::*;
use crate::mm::*;
use crate::mpool::*;
use crate::page::*;
use crate::std::*;
use crate::types::*;
use crate::utils::*;
use crate::vm::*;

use arrayvec::ArrayVec;

/// Copies data to an unmapped location by mapping it for write, copying the
/// data, then unmapping it.
///
/// The data is written so that it is available to all cores with the cache
/// disabled. When switching to the partitions, the caching is initially
/// disabled so the data must be available without the cache.
unsafe fn copy_to_unmapped(
    hypervisor_ptable: &mut PageTable<Stage1>,
    to: paddr_t,
    from: *const c_void,
    size: usize,
    ppool: &MPool,
) -> bool {
    let to_end = pa_add(to, size);

    if hypervisor_ptable
        .identity_map(to, to_end, Mode::W, ppool)
        .is_err()
    {
        return false;
    }

    memcpy_s(pa_addr(to) as *mut _, size, from, size);
    arch_mm_write_back_dcache(pa_addr(to), size);

    hypervisor_ptable.unmap(to, to_end, ppool).unwrap();

    true
}

/// Loads the primary VM.
pub unsafe fn load_primary(
    vm_manager: &mut VmManager,
    hypervisor_ptable: &mut PageTable<Stage1>,
    cpio: &MemIter,
    kernel_arg: uintreg_t,
    ppool: &MPool,
) -> Result<MemIter, ()> {
    let primary_begin = layout_primary_begin();

    let it = some_or!(find_file(&mut cpio.clone(), "vmlinuz\0".as_ptr()), {
        dlog!("Unable to find vmlinuz\n");
        return Err(());
    });

    dlog!(
        "Copying primary to {:p}\n",
        pa_addr(primary_begin) as *const u8
    );

    if !copy_to_unmapped(
        hypervisor_ptable,
        primary_begin,
        it.get_next() as usize as *mut _,
        it.len(),
        ppool,
    ) {
        dlog!("Unable to relocate kernel for primary vm.\n");
        return Err(());
    }

    let initrd = some_or!(find_file(&mut cpio.clone(), "initrd.img\0".as_ptr()), {
        dlog!("Unable to find initrd.img\n");
        return Err(());
    });

    let vm = vm_manager
        .new_vm(MAX_CPUS as spci_vcpu_count_t, ppool)
        .ok_or_else(|| {
            dlog!("Unable to initialise primary vm\n");
        })?;

    if vm.id != HF_PRIMARY_VM_ID {
        dlog!("Primary vm was not given correct id\n");
        return Err(());
    }

    // Map the 1TB of memory.
    // TODO: We should do a whitelist rather than blacklist.
    if vm
        .inner
        .get_mut()
        .ptable
        .identity_map(
            pa_init(0),
            pa_init(1024usize * 1024 * 1024 * 1024),
            Mode::R | Mode::W | Mode::X,
            ppool,
        )
        .is_err()
    {
        dlog!("Unable to initialise memory for primary vm\n");
        return Err(());
    }

    if !mm_vm_unmap_hypervisor(&mut (*vm).inner.get_mut_unchecked().ptable, ppool) {
        dlog!("Unable to unmap hypervisor from primary vm\n");
        return Err(());
    }

    vm.vcpus[0]
        .inner
        .lock() // TODO(HfO2): We can safely use get_mut() here
        .on(ipa_from_pa(primary_begin), kernel_arg);

    Ok(initrd)
}

/// Try to find a memory range of the given size within the given ranges, and
/// remove it from them. Return true on success, or false if no large enough
/// contiguous range is found.
fn carve_out_mem_range(
    mem_ranges: &mut [MemRange],
    size_to_find: u64,
) -> Result<(paddr_t, paddr_t), ()> {
    // TODO(b/116191358): Consider being cleverer about how we pack VMs
    // together, with a non-greedy algorithm.
    for mem_range in mem_ranges.iter_mut() {
        if size_to_find <= pa_difference(mem_range.begin, mem_range.end) as u64 {
            // This range is big enough, take some of it from the end and reduce
            // its size accordingly.
            let found_end = mem_range.end;
            let found_begin = pa_init(pa_addr(mem_range.end) - size_to_find as usize);
            mem_range.end = found_begin;
            return Ok((found_begin, found_end));
        }
    }

    Err(())
}

/// Given arrays of memory ranges before and after memory was removed for
/// secondary VMs, add the difference to the reserved ranges of the given
/// update. Return true on success, or false if there would be more than
/// MAX_MEM_RANGES reserved ranges after adding the new ones.
/// `before` and `after` must be arrays of exactly `mem_ranges_count` elements.
fn update_reserved_ranges(
    update: &mut BootParamsUpdate,
    before: &[MemRange],
    after: &[MemRange],
) -> Result<(), ()> {
    assert_eq!(before.len(), after.len());

    for (before, after) in before.iter().zip(after.iter()) {
        if pa_addr(after.begin) > pa_addr(before.begin) {
            if update.reserved_ranges_count >= MAX_MEM_RANGES {
                dlog!("Too many reserved ranges after loading secondary VMs.\n");
                return Err(());
            }

            update.reserved_ranges[update.reserved_ranges_count].begin = after.end;
            update.reserved_ranges[update.reserved_ranges_count].end = before.end;
            update.reserved_ranges_count += 1;
        }
    }

    Ok(())
}

/// Loads all secondary VMs into the memory ranges from the given params.
/// Memory reserved for the VMs is added to the `reserved_ranges` of `update`.
pub unsafe fn load_secondary(
    vm_manager: &mut VmManager,
    hypervisor_ptable: &mut PageTable<Stage1>,
    cpio: &MemIter,
    params: &BootParams,
    update: &mut BootParamsUpdate,
    ppool: &MPool,
) -> Result<(), ()> {
    let mut mem_ranges_available: ArrayVec<[MemRange; MAX_MEM_RANGES]> = ArrayVec::new();
    // static_assert(
    //  sizeof(mem_ranges_available) == sizeof(params->mem_ranges),
    //  "mem_range arrays must be the same size for memcpy.");

    const_assert!(mem::size_of::<MemRange>() * MAX_MEM_RANGES < 500);
    mem_ranges_available.set_len(MAX_MEM_RANGES);
    mem_ranges_available.clone_from_slice(&params.mem_ranges);
    mem_ranges_available.truncate(params.mem_ranges_count);

    let mut it = some_or!(find_file(&mut cpio.clone(), "vms.txt\0".as_ptr()), {
        dlog!("vms.txt is missing\n");
        return Ok(());
    });

    // Round the last addresses down to the page size.
    for mem_range in mem_ranges_available.iter_mut() {
        mem_range.end = pa_init(round_down(pa_addr(mem_range.end), PAGE_SIZE));
    }

    loop {
        // Note(HfO2): There is `while let (Some(x), Some(y)) = (...) {}` but it
        // is not short-circuiting.
        let mut mem = some_or!(it.parse_uint(), break);
        let cpu = some_or!(it.parse_uint(), break);
        let name = some_or!(it.parse_str(), break);
        let name_str = str::from_utf8_unchecked(name.as_slice());

        dlog!("Loading {}\n", name_str);

        let kernel = some_or!(find_file_memiter(&mut cpio.clone(), &name), {
            dlog!("Unable to load kernel\n");
            continue;
        });

        // Round up to page size.
        mem = (mem + PAGE_SIZE as u64 - 1) & !(PAGE_SIZE as u64 - 1);

        if mem < kernel.len() as u64 {
            dlog!("Kernel is larger than available memory\n");
            continue;
        }

        let (secondary_mem_begin, secondary_mem_end) = ok_or!(
            carve_out_mem_range(&mut mem_ranges_available, mem as u64),
            {
                dlog!("Not enough memory ({} bytes)\n", mem);
                continue;
            }
        );

        if !copy_to_unmapped(
            hypervisor_ptable,
            secondary_mem_begin,
            kernel.get_next() as usize as *const _,
            kernel.len(),
            ppool,
        ) {
            dlog!("Unable to copy kernel\n");
            continue;
        }

        let primary = vm_manager.get_mut(HF_PRIMARY_VM_ID).unwrap();

        // Deny the primary VM access to this memory.
        if primary
            .inner
            .get_mut()
            .ptable
            .unmap(secondary_mem_begin, secondary_mem_end, ppool)
            .is_err()
        {
            dlog!("Unable to unmap secondary VM from primary VM\n");
            return Err(());
        }

        let vm = some_or!(vm_manager.new_vm(cpu as spci_vcpu_count_t, ppool), {
            dlog!("Unable to initialise VM\n");
            continue;
        });

        // Grant the VM access to the memory.
        if vm
            .inner
            .get_mut()
            .ptable
            .identity_map(
                secondary_mem_begin,
                secondary_mem_end,
                Mode::R | Mode::W | Mode::X,
                ppool,
            )
            .is_err()
        {
            dlog!("Unable to initialise memory\n");
            continue;
        }

        dlog!(
            "Loaded with {} vcpus, entry at 0x{:x}\n",
            cpu,
            pa_addr(secondary_mem_begin)
        );

        let secondary_entry = ipa_from_pa(secondary_mem_begin);
        vcpu_secondary_reset_and_start(
            &mut vm.vcpus[0],
            secondary_entry,
            pa_difference(secondary_mem_begin, secondary_mem_end) as uintreg_t,
        );
    }

    // Add newly reserved areas to update params by looking at the difference
    // between the available ranges from the original params and the updated
    // mem_ranges_available. We assume that the number and order of available
    // ranges is the same, i.e. we don't remove any ranges above only make them
    // smaller.
    update_reserved_ranges(
        update,
        &params.mem_ranges[0..params.mem_ranges_count],
        &mem_ranges_available,
    )
}
<commit_msg>Remove a call to memcpy_s<commit_after>/*
 * Copyright 2019 Sanguk Park
 *
 * 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
 *
 *     https://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.
 */

use core::mem;
use core::ptr;
use core::str;

use crate::addr::*;
use crate::arch::*;
use crate::boot_params::*;
use crate::cpio::*;
use crate::cpu::*;
use crate::layout::*;
use crate::memiter::*;
use crate::mm::*;
use crate::mpool::*;
use crate::page::*;
use crate::types::*;
use crate::utils::*;
use crate::vm::*;

use arrayvec::ArrayVec;

/// Copies data to an unmapped location by mapping it for write, copying the
/// data, then unmapping it.
///
/// The data is written so that it is available to all cores with the cache
/// disabled. When switching to the partitions, the caching is initially
/// disabled so the data must be available without the cache.
unsafe fn copy_to_unmapped(
    hypervisor_ptable: &mut PageTable<Stage1>,
    to: paddr_t,
    from: *const c_void,
    size: usize,
    ppool: &MPool,
) -> bool {
    let to_end = pa_add(to, size);

    if hypervisor_ptable
        .identity_map(to, to_end, Mode::W, ppool)
        .is_err()
    {
        return false;
    }

    ptr::copy_nonoverlapping(from, pa_addr(to) as *mut _, size);
    arch_mm_write_back_dcache(pa_addr(to), size);

    hypervisor_ptable.unmap(to, to_end, ppool).unwrap();

    true
}

/// Loads the primary VM.
pub unsafe fn load_primary(
    vm_manager: &mut VmManager,
    hypervisor_ptable: &mut PageTable<Stage1>,
    cpio: &MemIter,
    kernel_arg: uintreg_t,
    ppool: &MPool,
) -> Result<MemIter, ()> {
    let primary_begin = layout_primary_begin();

    let it = some_or!(find_file(&mut cpio.clone(), "vmlinuz\0".as_ptr()), {
        dlog!("Unable to find vmlinuz\n");
        return Err(());
    });

    dlog!(
        "Copying primary to {:p}\n",
        pa_addr(primary_begin) as *const u8
    );

    if !copy_to_unmapped(
        hypervisor_ptable,
        primary_begin,
        it.get_next() as usize as *mut _,
        it.len(),
        ppool,
    ) {
        dlog!("Unable to relocate kernel for primary vm.\n");
        return Err(());
    }

    let initrd = some_or!(find_file(&mut cpio.clone(), "initrd.img\0".as_ptr()), {
        dlog!("Unable to find initrd.img\n");
        return Err(());
    });

    let vm = vm_manager
        .new_vm(MAX_CPUS as spci_vcpu_count_t, ppool)
        .ok_or_else(|| {
            dlog!("Unable to initialise primary vm\n");
        })?;

    if vm.id != HF_PRIMARY_VM_ID {
        dlog!("Primary vm was not given correct id\n");
        return Err(());
    }

    // Map the 1TB of memory.
    // TODO: We should do a whitelist rather than blacklist.
    if vm
        .inner
        .get_mut()
        .ptable
        .identity_map(
            pa_init(0),
            pa_init(1024usize * 1024 * 1024 * 1024),
            Mode::R | Mode::W | Mode::X,
            ppool,
        )
        .is_err()
    {
        dlog!("Unable to initialise memory for primary vm\n");
        return Err(());
    }

    if !mm_vm_unmap_hypervisor(&mut (*vm).inner.get_mut_unchecked().ptable, ppool) {
        dlog!("Unable to unmap hypervisor from primary vm\n");
        return Err(());
    }

    vm.vcpus[0]
        .inner
        .lock() // TODO(HfO2): We can safely use get_mut() here
        .on(ipa_from_pa(primary_begin), kernel_arg);

    Ok(initrd)
}

/// Try to find a memory range of the given size within the given ranges, and
/// remove it from them. Return true on success, or false if no large enough
/// contiguous range is found.
fn carve_out_mem_range(
    mem_ranges: &mut [MemRange],
    size_to_find: u64,
) -> Result<(paddr_t, paddr_t), ()> {
    // TODO(b/116191358): Consider being cleverer about how we pack VMs
    // together, with a non-greedy algorithm.
    for mem_range in mem_ranges.iter_mut() {
        if size_to_find <= pa_difference(mem_range.begin, mem_range.end) as u64 {
            // This range is big enough, take some of it from the end and reduce
            // its size accordingly.
            let found_end = mem_range.end;
            let found_begin = pa_init(pa_addr(mem_range.end) - size_to_find as usize);
            mem_range.end = found_begin;
            return Ok((found_begin, found_end));
        }
    }

    Err(())
}

/// Given arrays of memory ranges before and after memory was removed for
/// secondary VMs, add the difference to the reserved ranges of the given
/// update. Return true on success, or false if there would be more than
/// MAX_MEM_RANGES reserved ranges after adding the new ones.
/// `before` and `after` must be arrays of exactly `mem_ranges_count` elements.
fn update_reserved_ranges(
    update: &mut BootParamsUpdate,
    before: &[MemRange],
    after: &[MemRange],
) -> Result<(), ()> {
    assert_eq!(before.len(), after.len());

    for (before, after) in before.iter().zip(after.iter()) {
        if pa_addr(after.begin) > pa_addr(before.begin) {
            if update.reserved_ranges_count >= MAX_MEM_RANGES {
                dlog!("Too many reserved ranges after loading secondary VMs.\n");
                return Err(());
            }

            update.reserved_ranges[update.reserved_ranges_count].begin = after.end;
            update.reserved_ranges[update.reserved_ranges_count].end = before.end;
            update.reserved_ranges_count += 1;
        }
    }

    Ok(())
}

/// Loads all secondary VMs into the memory ranges from the given params.
/// Memory reserved for the VMs is added to the `reserved_ranges` of `update`.
pub unsafe fn load_secondary(
    vm_manager: &mut VmManager,
    hypervisor_ptable: &mut PageTable<Stage1>,
    cpio: &MemIter,
    params: &BootParams,
    update: &mut BootParamsUpdate,
    ppool: &MPool,
) -> Result<(), ()> {
    let mut mem_ranges_available: ArrayVec<[MemRange; MAX_MEM_RANGES]> = ArrayVec::new();
    // static_assert(
    //  sizeof(mem_ranges_available) == sizeof(params->mem_ranges),
    //  "mem_range arrays must be the same size for memcpy.");

    const_assert!(mem::size_of::<MemRange>() * MAX_MEM_RANGES < 500);
    mem_ranges_available.set_len(MAX_MEM_RANGES);
    mem_ranges_available.clone_from_slice(&params.mem_ranges);
    mem_ranges_available.truncate(params.mem_ranges_count);

    let mut it = some_or!(find_file(&mut cpio.clone(), "vms.txt\0".as_ptr()), {
        dlog!("vms.txt is missing\n");
        return Ok(());
    });

    // Round the last addresses down to the page size.
    for mem_range in mem_ranges_available.iter_mut() {
        mem_range.end = pa_init(round_down(pa_addr(mem_range.end), PAGE_SIZE));
    }

    loop {
        // Note(HfO2): There is `while let (Some(x), Some(y)) = (...) {}` but it
        // is not short-circuiting.
        let mut mem = some_or!(it.parse_uint(), break);
        let cpu = some_or!(it.parse_uint(), break);
        let name = some_or!(it.parse_str(), break);
        let name_str = str::from_utf8_unchecked(name.as_slice());

        dlog!("Loading {}\n", name_str);

        let kernel = some_or!(find_file_memiter(&mut cpio.clone(), &name), {
            dlog!("Unable to load kernel\n");
            continue;
        });

        // Round up to page size.
        mem = (mem + PAGE_SIZE as u64 - 1) & !(PAGE_SIZE as u64 - 1);

        if mem < kernel.len() as u64 {
            dlog!("Kernel is larger than available memory\n");
            continue;
        }

        let (secondary_mem_begin, secondary_mem_end) = ok_or!(
            carve_out_mem_range(&mut mem_ranges_available, mem as u64),
            {
                dlog!("Not enough memory ({} bytes)\n", mem);
                continue;
            }
        );

        if !copy_to_unmapped(
            hypervisor_ptable,
            secondary_mem_begin,
            kernel.get_next() as usize as *const _,
            kernel.len(),
            ppool,
        ) {
            dlog!("Unable to copy kernel\n");
            continue;
        }

        let primary = vm_manager.get_mut(HF_PRIMARY_VM_ID).unwrap();

        // Deny the primary VM access to this memory.
        if primary
            .inner
            .get_mut()
            .ptable
            .unmap(secondary_mem_begin, secondary_mem_end, ppool)
            .is_err()
        {
            dlog!("Unable to unmap secondary VM from primary VM\n");
            return Err(());
        }

        let vm = some_or!(vm_manager.new_vm(cpu as spci_vcpu_count_t, ppool), {
            dlog!("Unable to initialise VM\n");
            continue;
        });

        // Grant the VM access to the memory.
        if vm
            .inner
            .get_mut()
            .ptable
            .identity_map(
                secondary_mem_begin,
                secondary_mem_end,
                Mode::R | Mode::W | Mode::X,
                ppool,
            )
            .is_err()
        {
            dlog!("Unable to initialise memory\n");
            continue;
        }

        dlog!(
            "Loaded with {} vcpus, entry at 0x{:x}\n",
            cpu,
            pa_addr(secondary_mem_begin)
        );

        let secondary_entry = ipa_from_pa(secondary_mem_begin);
        vcpu_secondary_reset_and_start(
            &mut vm.vcpus[0],
            secondary_entry,
            pa_difference(secondary_mem_begin, secondary_mem_end) as uintreg_t,
        );
    }

    // Add newly reserved areas to update params by looking at the difference
    // between the available ranges from the original params and the updated
    // mem_ranges_available. We assume that the number and order of available
    // ranges is the same, i.e. we don't remove any ranges above only make them
    // smaller.
    update_reserved_ranges(
        update,
        &params.mem_ranges[0..params.mem_ranges_count],
        &mem_ranges_available,
    )
}
<|endoftext|>


<commit_before>extern crate digest;
extern crate indy_crypto;
extern crate sha2;
extern crate rust_base58;

use errors::common::CommonError;
use services::blob_storage::BlobStorageService;
use domain::anoncreds::revocation_registry_definition::RevocationRegistryDefinitionV1;

use self::indy_crypto::cl::{Tail, RevocationTailsAccessor, RevocationTailsGenerator};
use self::indy_crypto::errors::IndyCryptoError;
use self::digest::Input;

use self::rust_base58::{ToBase58, FromBase58};

use std::rc::Rc;

const TAILS_BLOB_TAG_SZ: u8 = 2;
const TAIL_SIZE: usize = Tail::BYTES_REPR_SIZE;

pub struct SDKTailsAccessor {
    tails_service: Rc<BlobStorageService>,
    tails_reader_handle: i32,
}

impl SDKTailsAccessor {
    pub fn new(tails_service: Rc<BlobStorageService>,
               tails_reader_handle: i32,
               rev_reg_def: &RevocationRegistryDefinitionV1) -> Result<SDKTailsAccessor, CommonError> {
        let tails_hash = rev_reg_def.value.tails_hash.from_base58()
            .map_err(|_| CommonError::InvalidState("Invalid base58 for Tails hash".to_string()))?;

        let tails_reader_handle = tails_service.open_blob(tails_reader_handle,
                                                          &rev_reg_def.value.tails_location,
                                                          tails_hash.as_slice())?;

        Ok(SDKTailsAccessor {
            tails_service,
            tails_reader_handle
        })
    }
}

impl Drop for SDKTailsAccessor {
    fn drop(&mut self) {
        #[allow(unused_must_use)] //TODO
            {
                self.tails_service.close(self.tails_reader_handle)
                    .map_err(map_err_err!());
            }
    }
}

impl RevocationTailsAccessor for SDKTailsAccessor {
    fn access_tail(&self, tail_id: u32, accessor: &mut FnMut(&Tail)) -> Result<(), IndyCryptoError> {
        debug!("access_tail >>> tail_id: {:?}",tail_id);

        let tail_bytes = self.tails_service
            .read(self.tails_reader_handle,
                  TAIL_SIZE,
                  TAIL_SIZE * tail_id as usize + TAILS_BLOB_TAG_SZ as usize)
            .map_err(|_|
                IndyCryptoError::InvalidState("Can't read tail bytes from blob storage".to_owned()))?; //TODO
        let tail = Tail::from_bytes(tail_bytes.as_slice())?;
        accessor(&tail);

        let res = ();

        debug!("access_tail <<< res: {:?}",res);

        Ok(res)
    }
}

pub fn store_tails_from_generator(service: Rc<BlobStorageService>,
                                  writer_handle: i32,
                                  rtg: &mut RevocationTailsGenerator) -> Result<(String, String), CommonError> {
    debug!("store_tails_from_generator >>> writer_handle: {:?}",writer_handle);

    let mut hasher = sha2::Sha256::default();

    let blob_handle = service.create_blob(writer_handle, hasher)?;

    let version = vec![0u8, TAILS_BLOB_TAG_SZ];
    hasher.process(version.as_slice());
    service.append(blob_handle, version.as_slice())?;

    while let Some(tail) = rtg.next()? {
        let tail_bytes = tail.to_bytes()?;
        hasher.process(tail_bytes.as_slice());
        service.append(blob_handle, tail_bytes.as_slice())?;
    }

    let res = service.finalize(blob_handle).map(|(location, hash)| (location, hash.to_base58()))?;

    debug!("store_tails_from_generator <<< res: {:?}", res);

    Ok(res)
}
<commit_msg>this hasher is not needed as the real hasher is in blob_storage/mod.rs<commit_after>extern crate digest;
extern crate indy_crypto;
extern crate sha2;
extern crate rust_base58;

use errors::common::CommonError;
use services::blob_storage::BlobStorageService;
use domain::anoncreds::revocation_registry_definition::RevocationRegistryDefinitionV1;

use self::indy_crypto::cl::{Tail, RevocationTailsAccessor, RevocationTailsGenerator};
use self::indy_crypto::errors::IndyCryptoError;
use self::digest::Input;

use self::rust_base58::{ToBase58, FromBase58};

use std::rc::Rc;

const TAILS_BLOB_TAG_SZ: u8 = 2;
const TAIL_SIZE: usize = Tail::BYTES_REPR_SIZE;

pub struct SDKTailsAccessor {
    tails_service: Rc<BlobStorageService>,
    tails_reader_handle: i32,
}

impl SDKTailsAccessor {
    pub fn new(tails_service: Rc<BlobStorageService>,
               tails_reader_handle: i32,
               rev_reg_def: &RevocationRegistryDefinitionV1) -> Result<SDKTailsAccessor, CommonError> {
        let tails_hash = rev_reg_def.value.tails_hash.from_base58()
            .map_err(|_| CommonError::InvalidState("Invalid base58 for Tails hash".to_string()))?;

        let tails_reader_handle = tails_service.open_blob(tails_reader_handle,
                                                          &rev_reg_def.value.tails_location,
                                                          tails_hash.as_slice())?;

        Ok(SDKTailsAccessor {
            tails_service,
            tails_reader_handle
        })
    }
}

impl Drop for SDKTailsAccessor {
    fn drop(&mut self) {
        #[allow(unused_must_use)] //TODO
            {
                self.tails_service.close(self.tails_reader_handle)
                    .map_err(map_err_err!());
            }
    }
}

impl RevocationTailsAccessor for SDKTailsAccessor {
    fn access_tail(&self, tail_id: u32, accessor: &mut FnMut(&Tail)) -> Result<(), IndyCryptoError> {
        debug!("access_tail >>> tail_id: {:?}",tail_id);

        let tail_bytes = self.tails_service
            .read(self.tails_reader_handle,
                  TAIL_SIZE,
                  TAIL_SIZE * tail_id as usize + TAILS_BLOB_TAG_SZ as usize)
            .map_err(|_|
                IndyCryptoError::InvalidState("Can't read tail bytes from blob storage".to_owned()))?; //TODO
        let tail = Tail::from_bytes(tail_bytes.as_slice())?;
        accessor(&tail);

        let res = ();

        debug!("access_tail <<< res: {:?}",res);

        Ok(res)
    }
}

pub fn store_tails_from_generator(service: Rc<BlobStorageService>,
                                  writer_handle: i32,
                                  rtg: &mut RevocationTailsGenerator) -> Result<(String, String), CommonError> {
    debug!("store_tails_from_generator >>> writer_handle: {:?}",writer_handle);

    let blob_handle = service.create_blob(writer_handle)?;

    let version = vec![0u8, TAILS_BLOB_TAG_SZ];
    service.append(blob_handle, version.as_slice())?;

    while let Some(tail) = rtg.next()? {
        let tail_bytes = tail.to_bytes()?;
        service.append(blob_handle, tail_bytes.as_slice())?;
    }

    let res = service.finalize(blob_handle).map(|(location, hash)| (location, hash.to_base58()))?;

    debug!("store_tails_from_generator <<< res: {:?}", res);

    Ok(res)
}
<|endoftext|>