<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::borrow::Borrow;
use std::path::Path;
use std::cmp::Ordering;
use std::io;
use std::io::ErrorKind;
use std::error::Error;

use uuid::Uuid;
use devicemapper::DM;
use serde_json;
use time;

use blockdev::{BlockDev, BlockDevSave};
use blockdev::{LinearDev, LinearSegment};
use raid::{RaidDev, RaidDevSave, RaidSegment, RaidLinearDev};
use thin::{ThinPoolDev, ThinPoolDevSave};
use thin::{ThinDev, ThinDevSave};
use types::{Sectors, SectorOffset, FroyoError};
use util::{align_to, clear_dev};
use consts::*;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct FroyoSave {
    name: String,
    id: String,
    block_devs: BTreeMap<String, BlockDevSave>,
    raid_devs: BTreeMap<String, RaidDevSave>,
    thin_pool_dev: ThinPoolDevSave,
    thin_devs: Vec<ThinDevSave>,
}

#[derive(Debug, Clone)]
pub struct Froyo {
    id: String,
    pub name: String,
    block_devs: BTreeMap<String, Rc<RefCell<BlockDev>>>,
    raid_devs: BTreeMap<String, Rc<RefCell<RaidDev>>>,
    thin_pool_dev: ThinPoolDev,
    thin_devs: Vec<ThinDev>,
}

impl Froyo {
    pub fn create<T>(name: &str, id: &str, paths: &[T], force: bool) -> Result<Froyo, FroyoError>
        where T: Borrow<Path>
    {
        let mut block_devs = BTreeMap::new();
        for path in paths {
            let bd = Rc::new(RefCell::new(
                try!(BlockDev::initialize(&id, path.borrow(), force))));
            block_devs.insert(RefCell::borrow(&bd).id.clone(), bd.clone());
        }

        if paths.len() < 2 {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput, "At least 2 block devices must be given")))
        }

        if paths.len() > 8 {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput,
                format!("Max supported devices is 8, {} given", paths.len()))))
        }

        let dm = try!(DM::new());

        let mut raid_devs = BTreeMap::new();
        loop {
            if let Some(rd) = try!(
                Froyo::create_redundant_zone(&dm, name, &block_devs, force)) {
                raid_devs.insert(rd.id.clone(), Rc::new(RefCell::new(rd)));
            } else {
                break
            }
        }

        let thin_pool_dev = try!(ThinPoolDev::new(&dm, name, &raid_devs));
        let mut thin_devs = Vec::new();

        // Create an initial 1TB thin dev
        thin_devs.push(try!(ThinDev::create(
            &dm,
            name,
            0,
            "xfs",
            Sectors::new(1024 * 1024 * 1024 * 1024 / SECTOR_SIZE),
            &thin_pool_dev)));

        Ok(Froyo {
            name: name.to_owned(),
            id: id.to_owned(),
            block_devs: block_devs,
            raid_devs: raid_devs,
            thin_pool_dev: thin_pool_dev,
            thin_devs: thin_devs,
        })
    }

    pub fn to_save(&self) -> FroyoSave {
        FroyoSave {
            name: self.name.to_owned(),
            id: self.id.to_owned(),
            block_devs: self.block_devs.iter()
                .map(|(id, bd)| (id.clone(), RefCell::borrow(bd).to_save()))
                .collect(),
            raid_devs: self.raid_devs.iter()
                .map(|(id, rd)| (id.clone(), RefCell::borrow(rd).to_save()))
                .collect(),
            thin_pool_dev: self.thin_pool_dev.to_save(),
            thin_devs: self.thin_devs.iter()
                .map(|x| x.to_save())
                .collect(),
        }
    }

    pub fn find_all() -> Result<Vec<Froyo>, FroyoError> {
        // We could have BlockDevs for multiple Froyodevs.
        // Group them by Froyo uuid.
        let mut froyo_devs = BTreeMap::new();
        for bd in try!(BlockDev::find_all()) {
            froyo_devs.entry(bd.froyodev_id.clone())
                .or_insert(Vec::new())
                .push(bd);
        }

        let mut froyos = Vec::new();
        for (froyo_id, bds) in froyo_devs {
            let buf = {
                // get newest metadata across all blockdevs and in either MDA
                let newest_bd = bds.iter()
                    .map(|bd| {
                        let mda = match bd.mdaa.last_updated.cmp(&bd.mdab.last_updated) {
                            Ordering::Less => &bd.mdab,
                            Ordering::Greater => &bd.mdaa,
                            Ordering::Equal => &bd.mdab,
                        };
                        (mda.last_updated, bd)
                    })
                    .max_by_key(|&(tm, _)| tm)
                    .unwrap().1;
                try!(newest_bd.read_mdax())
            };
            let s = String::from_utf8_lossy(&buf).into_owned();

            let froyo_save = try!(serde_json::from_str::<FroyoSave>(&s));

            froyos.push(try!(Froyo::from_save(froyo_save, froyo_id, bds)));
        }

        Ok(froyos)
    }

    fn from_save(froyo_save: FroyoSave, froyo_id: String, blockdevs: Vec<BlockDev>)
                 -> Result<Froyo, FroyoError> {
        let mut bd_map = blockdevs.into_iter()
            .map(|x| (x.id.clone(), x))
            .collect::<BTreeMap<_, _>>();

        let mut block_devs = BTreeMap::new();
        for (id, sbd) in &froyo_save.block_devs {
            match bd_map.remove(id) {
                Some(x) => { block_devs.insert(id.clone(), Rc::new(RefCell::new(x))); },
                None => ::dbgp!("missing a blockdev: id {} path {}", id,
                              sbd.path.display()),
            }
        }

        for (_, bd) in bd_map {
            dbgp!("{} header indicates it's part of {} but not found in metadata",
                  bd.path.display(), froyo_save.name);
        }

        match froyo_save.block_devs.len() - block_devs.len() {
            0 => dbgp!("All {} block devices found for {}",
                       block_devs.len(), froyo_save.name),
            num @ 1...FROYO_REDUNDANCY => dbgp!("Missing {} of {} drives from {}, can continue",
                                                num, froyo_save.block_devs.len(), froyo_save.name),
            num @ _ => return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("{} of {} devices missing from {}",
                        num, froyo_save.block_devs.len(), froyo_save.name)))),
        }

        let dm = try!(DM::new());

        let mut raid_devs = BTreeMap::new();
        for (id, srd) in froyo_save.raid_devs.iter() {
            let mut linear_devs = Vec::new();
            for (m_num, sld) in srd.members.iter().enumerate() {
                match block_devs.get(&sld.parent) {
                    Some(bd) => {
                        let ld = Rc::new(RefCell::new(try!(LinearDev::create(
                            &dm, &format!("{}-{}-{}", froyo_save.name, id, m_num),
                            bd, &sld.meta_segments, &sld.data_segments))));

                        bd.borrow_mut().linear_devs.push(ld.clone());
                        linear_devs.push(ld);
                    },
                    None => dbgp!("could not find parent {} for a linear device", sld.parent),
                }
            }

            // TODO: handle when devs is less than what's in srd
            let rd = Rc::new(RefCell::new(try!(RaidDev::create(
                &dm,
                &froyo_save.name,
                id.clone(),
                linear_devs,
                srd.stripe_sectors,
                srd.region_sectors))));

            let id = RefCell::borrow(&rd).id.clone();
            raid_devs.insert(id, rd);
        }

        let thin_pool_dev = {
            let tpd = &froyo_save.thin_pool_dev;

            let meta_name = format!("thin-meta-{}", froyo_save.name);
            let mut raid_segments = Vec::new();
            for seg in &tpd.meta_dev.segments {
                let parent = try!(raid_devs.get(&seg.parent).ok_or(
                    io::Error::new(io::ErrorKind::InvalidInput,
                                   "Could not find meta's parent")));
                raid_segments.push(
                    RaidSegment::new(seg.start, seg.length, parent));
            }

            let meta_raid_dev = try!(RaidLinearDev::create(
                &dm,
                &meta_name,
                &tpd.meta_dev.id,
                raid_segments));

            let data_name = format!("thin-data-{}", froyo_save.name);
            let mut raid_segments = Vec::new();
            for seg in &tpd.data_dev.segments {
                let parent = try!(raid_devs.get(&seg.parent).ok_or(
                    io::Error::new(io::ErrorKind::InvalidInput,
                                   "Could not find data's parent")));
                raid_segments.push(
                    RaidSegment::new(seg.start, seg.length, parent));
            }

            let data_raid_dev = try!(RaidLinearDev::create(
                &dm,
                &data_name,
                &tpd.data_dev.id,
                raid_segments));

            try!(ThinPoolDev::create(
                &dm,
                &froyo_save.name,
                tpd.data_block_size,
                tpd.low_water_blocks,
                meta_raid_dev,
                data_raid_dev))
        };

        let mut thin_devs = Vec::new();
        for std in &froyo_save.thin_devs {
            thin_devs.push(try!(ThinDev::create(
                &dm,
                &froyo_save.name,
                std.thin_number,
                &std.fs,
                std.size,
                &thin_pool_dev)));
        }

        Ok(Froyo {
            name: froyo_save.name.to_owned(),
            id: froyo_id.to_owned(),
            block_devs: block_devs,
            raid_devs: raid_devs,
            thin_pool_dev: thin_pool_dev,
            thin_devs: thin_devs,
        })
    }

    // Try to make an as-large-as-possible redundant device from the
    // given block devices.
    fn create_redundant_zone(
        dm: &DM,
        name: &str,
        block_devs: &BTreeMap<String, Rc<RefCell<BlockDev>>>,
        force: bool)
        -> Result<Option<RaidDev>, FroyoError> {

        // TODO: Make sure name has only chars we can use in a DM name

        // get common data area size, allowing for Froyo data at start and end
        let mut bd_areas: Vec<_> = block_devs.iter()
            .filter_map(|(_, bd)| {
                match RefCell::borrow(bd).largest_free_area() {
                    Some(x) => Some((bd.clone(), x)),
                    None => None,
                }
            })
            .filter(|&(_, (_, len))| len >= MIN_DATA_ZONE_SECTORS)
            .collect();

        // Not enough devs with room for a raid device
        if bd_areas.len() < 2 {
            return Ok(None)
        }

        let common_free_sectors = bd_areas.iter()
            .map(|&(_, (_, len))| len)
            .min()
            .unwrap();

        let (region_count, region_sectors) = {
            let mut region_sectors = DEFAULT_REGION_SECTORS;
            while *common_free_sectors / *region_sectors > MAX_REGIONS {
                region_sectors = Sectors::new(*region_sectors * 2);
            }

            let partial_region = match common_free_sectors % region_sectors == Sectors::new(0) {
                true => Sectors::new(0),
                false => Sectors::new(1),
            };

            (common_free_sectors / region_sectors + partial_region, region_sectors)
        };

        // each region needs 1 bit in the write intent bitmap
        let mdata_sectors = Sectors::new(align_to(8192 + (*region_count / 8) , SECTOR_SIZE)
                                    .next_power_of_two()
                                    / SECTOR_SIZE);
        // data size must be multiple of stripe size
        let data_sectors = (common_free_sectors - mdata_sectors) & Sectors::new(!(*STRIPE_SECTORS-1));

        let raid_uuid = Uuid::new_v4().to_simple_string();

        let mut linear_devs = Vec::new();
        for (num, &mut(ref mut bd, (sector_start, _))) in bd_areas.iter_mut().enumerate() {
            let mdata_sector_start = sector_start;
            let data_sector_start = SectorOffset::new(*mdata_sector_start + *mdata_sectors);

            let linear = Rc::new(RefCell::new(try!(LinearDev::create(
                &dm,
                &format!("{}-{}-{}", name, raid_uuid, num),
                bd,
                &vec![LinearSegment {
                    start: mdata_sector_start,
                    length: mdata_sectors,
                }],
                &vec![LinearSegment {
                    start: data_sector_start,
                    length: data_sectors,
                    }]))));

            if force {
                try!(clear_dev(&RefCell::borrow(&linear).meta_dev));
            }

            bd.borrow_mut().linear_devs.push(linear.clone());
            linear_devs.push(linear);
        }

        let raid = try!(RaidDev::create(
            &dm,
            &name,
            raid_uuid,
            linear_devs,
            STRIPE_SECTORS,
            region_sectors));

        Ok(Some(raid))
    }

    pub fn reshape(&mut self) -> io::Result<()> {
        Ok(())
    }

    pub fn save_state(&self) -> Result<(), FroyoError> {
        let froyo_info = self.to_save();
        let metadata = try!(serde_json::to_string(&froyo_info));
        let current_time = time::now().to_timespec();

        for (_, bd) in &self.block_devs {
            try!(bd.borrow_mut().save_state(&current_time, metadata.as_bytes()))
        }

        Ok(())
    }
}

<commit_msg>Froyo: Remove unused method<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::borrow::Borrow;
use std::path::Path;
use std::cmp::Ordering;
use std::io;
use std::io::ErrorKind;
use std::error::Error;

use uuid::Uuid;
use devicemapper::DM;
use serde_json;
use time;

use blockdev::{BlockDev, BlockDevSave};
use blockdev::{LinearDev, LinearSegment};
use raid::{RaidDev, RaidDevSave, RaidSegment, RaidLinearDev};
use thin::{ThinPoolDev, ThinPoolDevSave};
use thin::{ThinDev, ThinDevSave};
use types::{Sectors, SectorOffset, FroyoError};
use util::{align_to, clear_dev};
use consts::*;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct FroyoSave {
    name: String,
    id: String,
    block_devs: BTreeMap<String, BlockDevSave>,
    raid_devs: BTreeMap<String, RaidDevSave>,
    thin_pool_dev: ThinPoolDevSave,
    thin_devs: Vec<ThinDevSave>,
}

#[derive(Debug, Clone)]
pub struct Froyo {
    id: String,
    pub name: String,
    block_devs: BTreeMap<String, Rc<RefCell<BlockDev>>>,
    raid_devs: BTreeMap<String, Rc<RefCell<RaidDev>>>,
    thin_pool_dev: ThinPoolDev,
    thin_devs: Vec<ThinDev>,
}

impl Froyo {
    pub fn create<T>(name: &str, id: &str, paths: &[T], force: bool) -> Result<Froyo, FroyoError>
        where T: Borrow<Path>
    {
        let mut block_devs = BTreeMap::new();
        for path in paths {
            let bd = Rc::new(RefCell::new(
                try!(BlockDev::initialize(&id, path.borrow(), force))));
            block_devs.insert(RefCell::borrow(&bd).id.clone(), bd.clone());
        }

        if paths.len() < 2 {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput, "At least 2 block devices must be given")))
        }

        if paths.len() > 8 {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput,
                format!("Max supported devices is 8, {} given", paths.len()))))
        }

        let dm = try!(DM::new());

        let mut raid_devs = BTreeMap::new();
        loop {
            if let Some(rd) = try!(
                Froyo::create_redundant_zone(&dm, name, &block_devs, force)) {
                raid_devs.insert(rd.id.clone(), Rc::new(RefCell::new(rd)));
            } else {
                break
            }
        }

        let thin_pool_dev = try!(ThinPoolDev::new(&dm, name, &raid_devs));
        let mut thin_devs = Vec::new();

        // Create an initial 1TB thin dev
        thin_devs.push(try!(ThinDev::create(
            &dm,
            name,
            0,
            "xfs",
            Sectors::new(1024 * 1024 * 1024 * 1024 / SECTOR_SIZE),
            &thin_pool_dev)));

        Ok(Froyo {
            name: name.to_owned(),
            id: id.to_owned(),
            block_devs: block_devs,
            raid_devs: raid_devs,
            thin_pool_dev: thin_pool_dev,
            thin_devs: thin_devs,
        })
    }

    pub fn to_save(&self) -> FroyoSave {
        FroyoSave {
            name: self.name.to_owned(),
            id: self.id.to_owned(),
            block_devs: self.block_devs.iter()
                .map(|(id, bd)| (id.clone(), RefCell::borrow(bd).to_save()))
                .collect(),
            raid_devs: self.raid_devs.iter()
                .map(|(id, rd)| (id.clone(), RefCell::borrow(rd).to_save()))
                .collect(),
            thin_pool_dev: self.thin_pool_dev.to_save(),
            thin_devs: self.thin_devs.iter()
                .map(|x| x.to_save())
                .collect(),
        }
    }

    pub fn find_all() -> Result<Vec<Froyo>, FroyoError> {
        // We could have BlockDevs for multiple Froyodevs.
        // Group them by Froyo uuid.
        let mut froyo_devs = BTreeMap::new();
        for bd in try!(BlockDev::find_all()) {
            froyo_devs.entry(bd.froyodev_id.clone())
                .or_insert(Vec::new())
                .push(bd);
        }

        let mut froyos = Vec::new();
        for (froyo_id, bds) in froyo_devs {
            let buf = {
                // get newest metadata across all blockdevs and in either MDA
                let newest_bd = bds.iter()
                    .map(|bd| {
                        let mda = match bd.mdaa.last_updated.cmp(&bd.mdab.last_updated) {
                            Ordering::Less => &bd.mdab,
                            Ordering::Greater => &bd.mdaa,
                            Ordering::Equal => &bd.mdab,
                        };
                        (mda.last_updated, bd)
                    })
                    .max_by_key(|&(tm, _)| tm)
                    .unwrap().1;
                try!(newest_bd.read_mdax())
            };
            let s = String::from_utf8_lossy(&buf).into_owned();

            let froyo_save = try!(serde_json::from_str::<FroyoSave>(&s));

            froyos.push(try!(Froyo::from_save(froyo_save, froyo_id, bds)));
        }

        Ok(froyos)
    }

    fn from_save(froyo_save: FroyoSave, froyo_id: String, blockdevs: Vec<BlockDev>)
                 -> Result<Froyo, FroyoError> {
        let mut bd_map = blockdevs.into_iter()
            .map(|x| (x.id.clone(), x))
            .collect::<BTreeMap<_, _>>();

        let mut block_devs = BTreeMap::new();
        for (id, sbd) in &froyo_save.block_devs {
            match bd_map.remove(id) {
                Some(x) => { block_devs.insert(id.clone(), Rc::new(RefCell::new(x))); },
                None => ::dbgp!("missing a blockdev: id {} path {}", id,
                              sbd.path.display()),
            }
        }

        for (_, bd) in bd_map {
            dbgp!("{} header indicates it's part of {} but not found in metadata",
                  bd.path.display(), froyo_save.name);
        }

        match froyo_save.block_devs.len() - block_devs.len() {
            0 => dbgp!("All {} block devices found for {}",
                       block_devs.len(), froyo_save.name),
            num @ 1...FROYO_REDUNDANCY => dbgp!("Missing {} of {} drives from {}, can continue",
                                                num, froyo_save.block_devs.len(), froyo_save.name),
            num @ _ => return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("{} of {} devices missing from {}",
                        num, froyo_save.block_devs.len(), froyo_save.name)))),
        }

        let dm = try!(DM::new());

        let mut raid_devs = BTreeMap::new();
        for (id, srd) in froyo_save.raid_devs.iter() {
            let mut linear_devs = Vec::new();
            for (m_num, sld) in srd.members.iter().enumerate() {
                match block_devs.get(&sld.parent) {
                    Some(bd) => {
                        let ld = Rc::new(RefCell::new(try!(LinearDev::create(
                            &dm, &format!("{}-{}-{}", froyo_save.name, id, m_num),
                            bd, &sld.meta_segments, &sld.data_segments))));

                        bd.borrow_mut().linear_devs.push(ld.clone());
                        linear_devs.push(ld);
                    },
                    None => dbgp!("could not find parent {} for a linear device", sld.parent),
                }
            }

            // TODO: handle when devs is less than what's in srd
            let rd = Rc::new(RefCell::new(try!(RaidDev::create(
                &dm,
                &froyo_save.name,
                id.clone(),
                linear_devs,
                srd.stripe_sectors,
                srd.region_sectors))));

            let id = RefCell::borrow(&rd).id.clone();
            raid_devs.insert(id, rd);
        }

        let thin_pool_dev = {
            let tpd = &froyo_save.thin_pool_dev;

            let meta_name = format!("thin-meta-{}", froyo_save.name);
            let mut raid_segments = Vec::new();
            for seg in &tpd.meta_dev.segments {
                let parent = try!(raid_devs.get(&seg.parent).ok_or(
                    io::Error::new(io::ErrorKind::InvalidInput,
                                   "Could not find meta's parent")));
                raid_segments.push(
                    RaidSegment::new(seg.start, seg.length, parent));
            }

            let meta_raid_dev = try!(RaidLinearDev::create(
                &dm,
                &meta_name,
                &tpd.meta_dev.id,
                raid_segments));

            let data_name = format!("thin-data-{}", froyo_save.name);
            let mut raid_segments = Vec::new();
            for seg in &tpd.data_dev.segments {
                let parent = try!(raid_devs.get(&seg.parent).ok_or(
                    io::Error::new(io::ErrorKind::InvalidInput,
                                   "Could not find data's parent")));
                raid_segments.push(
                    RaidSegment::new(seg.start, seg.length, parent));
            }

            let data_raid_dev = try!(RaidLinearDev::create(
                &dm,
                &data_name,
                &tpd.data_dev.id,
                raid_segments));

            try!(ThinPoolDev::create(
                &dm,
                &froyo_save.name,
                tpd.data_block_size,
                tpd.low_water_blocks,
                meta_raid_dev,
                data_raid_dev))
        };

        let mut thin_devs = Vec::new();
        for std in &froyo_save.thin_devs {
            thin_devs.push(try!(ThinDev::create(
                &dm,
                &froyo_save.name,
                std.thin_number,
                &std.fs,
                std.size,
                &thin_pool_dev)));
        }

        Ok(Froyo {
            name: froyo_save.name.to_owned(),
            id: froyo_id.to_owned(),
            block_devs: block_devs,
            raid_devs: raid_devs,
            thin_pool_dev: thin_pool_dev,
            thin_devs: thin_devs,
        })
    }

    // Try to make an as-large-as-possible redundant device from the
    // given block devices.
    fn create_redundant_zone(
        dm: &DM,
        name: &str,
        block_devs: &BTreeMap<String, Rc<RefCell<BlockDev>>>,
        force: bool)
        -> Result<Option<RaidDev>, FroyoError> {

        // TODO: Make sure name has only chars we can use in a DM name

        // get common data area size, allowing for Froyo data at start and end
        let mut bd_areas: Vec<_> = block_devs.iter()
            .filter_map(|(_, bd)| {
                match RefCell::borrow(bd).largest_free_area() {
                    Some(x) => Some((bd.clone(), x)),
                    None => None,
                }
            })
            .filter(|&(_, (_, len))| len >= MIN_DATA_ZONE_SECTORS)
            .collect();

        // Not enough devs with room for a raid device
        if bd_areas.len() < 2 {
            return Ok(None)
        }

        let common_free_sectors = bd_areas.iter()
            .map(|&(_, (_, len))| len)
            .min()
            .unwrap();

        let (region_count, region_sectors) = {
            let mut region_sectors = DEFAULT_REGION_SECTORS;
            while *common_free_sectors / *region_sectors > MAX_REGIONS {
                region_sectors = Sectors::new(*region_sectors * 2);
            }

            let partial_region = match common_free_sectors % region_sectors == Sectors::new(0) {
                true => Sectors::new(0),
                false => Sectors::new(1),
            };

            (common_free_sectors / region_sectors + partial_region, region_sectors)
        };

        // each region needs 1 bit in the write intent bitmap
        let mdata_sectors = Sectors::new(align_to(8192 + (*region_count / 8) , SECTOR_SIZE)
                                    .next_power_of_two()
                                    / SECTOR_SIZE);
        // data size must be multiple of stripe size
        let data_sectors = (common_free_sectors - mdata_sectors) & Sectors::new(!(*STRIPE_SECTORS-1));

        let raid_uuid = Uuid::new_v4().to_simple_string();

        let mut linear_devs = Vec::new();
        for (num, &mut(ref mut bd, (sector_start, _))) in bd_areas.iter_mut().enumerate() {
            let mdata_sector_start = sector_start;
            let data_sector_start = SectorOffset::new(*mdata_sector_start + *mdata_sectors);

            let linear = Rc::new(RefCell::new(try!(LinearDev::create(
                &dm,
                &format!("{}-{}-{}", name, raid_uuid, num),
                bd,
                &vec![LinearSegment {
                    start: mdata_sector_start,
                    length: mdata_sectors,
                }],
                &vec![LinearSegment {
                    start: data_sector_start,
                    length: data_sectors,
                    }]))));

            if force {
                try!(clear_dev(&RefCell::borrow(&linear).meta_dev));
            }

            bd.borrow_mut().linear_devs.push(linear.clone());
            linear_devs.push(linear);
        }

        let raid = try!(RaidDev::create(
            &dm,
            &name,
            raid_uuid,
            linear_devs,
            STRIPE_SECTORS,
            region_sectors));

        Ok(Some(raid))
    }

    pub fn save_state(&self) -> Result<(), FroyoError> {
        let froyo_info = self.to_save();
        let metadata = try!(serde_json::to_string(&froyo_info));
        let current_time = time::now().to_timespec();

        for (_, bd) in &self.block_devs {
            try!(bd.borrow_mut().save_state(&current_time, metadata.as_bytes()))
        }

        Ok(())
    }
}

<|endoftext|>


<commit_before>//! Unimplemented.
<commit_msg>Finish R_ext/Print.h as ext/print.rs<commit_after>// automatically generated by rust-bindgen

#[allow(non_camel_case_types)]
pub type va_list = [va_list_tag; 1usize];

#[repr(C)]
#[derive(Copy)]
pub struct va_list_tag {
    pub gp_offset: ::libc::c_uint,
    pub fp_offset: ::libc::c_uint,
    pub overflow_arg_area: *mut ::libc::c_void,
    pub reg_save_area: *mut ::libc::c_void,
}

impl ::std::clone::Clone for va_list_tag {
    fn clone(&self) -> Self {
        *self
    }
}

impl ::std::default::Default for va_list_tag {
    fn default() -> Self {
        unsafe { ::std::mem::zeroed() }
    }
}

#[link(name = "R")]
extern {
    pub fn Rprintf(arg1: *const ::libc::c_char, ...) -> ();
    pub fn REprintf(arg1: *const ::libc::c_char, ...) -> ();
    pub fn Rvprintf(arg1: *const ::libc::c_char, arg2: va_list) -> ();
    pub fn REvprintf(arg1: *const ::libc::c_char, arg2: va_list) -> ();
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::collections::{BTreeMap};
use std::collections::btree_map::{Entry};
use std::{fmt, cmp};
use std::fs::{File};
use std::io::{Result, Read, Write};
use std::string::ToString;
use rustc_serialize::{Decodable};
use rustc_serialize::json::{Json, ToJson, Decoder};

/**************************/
/*** Struct definitions ***/
/**************************/

#[derive(RustcDecodable, PartialEq, Debug)]
pub struct Node {
	id: NodeIndex,
    pub props: BTreeMap<Box<String>, Box<String>>
}
#[derive(RustcDecodable, Debug)]
pub struct Edge {
	pub labels: Vec<String>
}

#[derive(RustcDecodable, Debug)]
pub struct Graph {
	pub nodes: BTreeMap<NodeIndex, Node>,
	pub edges: BTreeMap<NodeIndex, BTreeMap<NodeIndex, Edge>>
}

//#[derive(Eq, Hash, TotalEq, RustcDecodable, RustcEncodable)]
pub type NodeIndex = usize;

/***********************/
/*** Implementations ***/
/***********************/

/*** Node ***/

/// Used to give a string representation for Node
impl fmt::Display for Node {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Node<id={}, props=", self.id);
		for (k, v) in self.props.iter() {
			write!(f, "{}, {}", k, v);
		}
		write!(f, ">")
	}
}

/// Used to convert a Node to JSON
impl ToJson for Node {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		let mut props = BTreeMap::new();
		d.insert("id".to_owned(), self.id.to_json());
		for (&ref k, &ref v) in self.props.iter() {
			props.insert(*k.clone(), Json::String(*v.clone()));
		}
		d.insert("props".to_owned(), Json::Object(props));
		Json::Object(d)
	}
}

impl ToJson for Edge {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		d.insert("labels".to_string(), Json::Array(self.labels.iter().map(|l| Json::String(l.to_string())).collect()));
		Json::Object(d)
	}
}

impl ToJson for Graph {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		let mut edge_json_map = BTreeMap::new();
		d.insert("nodes".to_string(), Json::Object(self.nodes.iter().map(|(i, n)| (i.to_string(), n.to_json())).collect()));
		for (index, edge) in self.edges.iter() {
			edge_json_map.insert(index.to_string(), Json::Object(edge.iter().map(|(i, n)| (i.to_string(), n.to_json())).collect()));
		}
		d.insert("edges".to_string(), Json::Object(edge_json_map));
		Json::Object(d)
	}
}

/*** Edge ***/

/// Used to give a string representation for Edge
impl fmt::Display for Edge {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Edge<labels={}>", self.labels.join(","))
	}
}

impl cmp::PartialEq for Edge {
	fn eq(&self, other: &Edge) -> bool {
		self.labels == other.labels
	}
}

/*** Graph ***/

/// Used to give a string representation for Graph
// impl fmt::Display for Graph {
// 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 		write!(f.buf, "Graph (\n\tnodes = {}\n\tedges = {}\n)", self.nodes, self.edges)
// 	}
// }

impl Graph {

	/// Creates a new graph with empty BTreeMaps
	pub fn new() -> Graph {
		Graph { nodes: BTreeMap::new(), edges: BTreeMap::new() }
	}

	/// Encode and decode from file

	pub fn read_from_file(name: String) -> Graph {
		let mut contents = String::new();
		let mut file:File = File::open(name).unwrap();

		file.read_to_string(&mut contents).unwrap();
		let jsonstring = match Json::from_str(&contents) {
			Ok(a) => a,
			Err(e) => panic!("Error reading JSON string: {}", e)
		};

		let mut decoder = Decoder::new(jsonstring);
		match Decodable::decode(&mut decoder) {
			Ok(x) => x,
			Err(e) => panic!("Could not decode to graph: {}", e)
		}
	}

	pub fn write_to_file(&self, name: &'static str) -> Result<usize> {
		let mut file = try!(File::create(name));
		file.write(self.to_json().to_string().into_bytes().as_slice())
	}

	/*******************/
	/****** Nodes ******/
	/*******************/

	/// Gets the next node index
	pub fn next_node_index(&self) -> NodeIndex {
		self.nodes.len() + 1
	}

	/// Adds a Node to the Graph with a vector of attributes and a BTreeMap of properties
	pub fn add_node(&mut self, attr: &[&str], props: BTreeMap<Box<String>, Box<String>>) -> NodeIndex {
		let idx = self.next_node_index();
		self.nodes.insert(idx, Node { id: idx, props: props });
		// TODO This is weird
		for a in attr.iter() {
			self.add_edge(idx, idx, a.to_string());
		}
		idx
	}

	/// Removes a Node from the Graph given a NodeIndex
	pub fn remove_node(&mut self, idx: NodeIndex) -> Option<Node> {
		// TODO should also remove the attached edges
		match self.nodes.remove(&idx) {
			Some(n) => Some(n),
			None => None
		}
	}

	/// Get Nodes with a given attribute
	pub fn nodes_with_attr<'a>(&'a self, attr: &String) -> Vec<&Node> {
		self.nodes.values().filter(|node|
			if let Some(e) = self.edges.get(&node.id) {
				if let Some(edge) = e.get(&node.id) {
					edge.labels.contains(attr)
				} else {
					false
				}
			}
			else {
				false
			}).collect()
	}

	/// Get Nodes with a key-value pair
	pub fn nodes_with_prop<'a>(&'a self, key: &String, value: &String) -> Vec<&Node> {
		self.nodes.values().filter(|node|
			node.props.iter().find(|&(k, v)| **k == *key && **v == *value ).is_some()).collect()
	}

	/*******************/
	/****** Edges ******/
	/*******************/

	/// Add an Edge to the graph from the source NodeIndex to the target NodeIndex with a label
	pub fn add_edge<'a>(&'a mut self, source: NodeIndex, target: NodeIndex, label: String) -> & mut Edge {
		//map.entry(key).get().unwrap_or_else(|v| v.insert(default))
		let src_map = self.edges.entry(source).or_insert(BTreeMap::new());
		match src_map.entry(target) {
			Entry::Vacant(e) => {e.insert(Edge { labels: vec![label] });},
			Entry::Occupied(mut e) => if e.get().labels.contains(&label) { e.get_mut().labels.push(label); } else {()}
		};
		src_map.get_mut(&source).unwrap()
	}

	/// Get Edges with a given label
	pub fn edges_with_label<'a>(&'a self, label: &String) -> BTreeMap<&'a NodeIndex, BTreeMap<&'a NodeIndex, &'a Edge>> {
		let mut edges = BTreeMap::<&NodeIndex, BTreeMap<&NodeIndex, &Edge>>::new();
		for (src, map) in self.edges.iter() {
			let filtered: BTreeMap<&NodeIndex, &Edge> = map.iter().filter(|&(_idx, edge)| edge.labels.contains(label)).collect();
			if filtered.len() > 0 {
				edges.insert(src, filtered);
			}
		}
		edges
	}

	/// Get Nodes with a given label from a source NodeIndex
	pub fn edges_with_label_from<'a>(&'a self, source: NodeIndex, label: String) -> Vec<&'a Node> {
		if let Some(edge) = self.edges.get(&source) {
		edge.iter().filter_map(
			|(&idx, edge)|
				if edge.labels.contains(&label) {
					self.nodes.get(&idx)
				} else {
					None
				}).collect()
			} else {
				vec![]
			}
	}

}
<commit_msg>Removed code causing warnings<commit_after>#![allow(dead_code)]

use std::collections::{BTreeMap};
use std::collections::btree_map::{Entry};
use std::{fmt, cmp};
use std::fs::{File};
use std::io::{Result, Read, Write};
use std::string::ToString;
use rustc_serialize::{Decodable};
use rustc_serialize::json::{Json, ToJson, Decoder};

/**************************/
/*** Struct definitions ***/
/**************************/

#[derive(RustcDecodable, PartialEq, Debug)]
pub struct Node {
	id: NodeIndex,
    pub props: BTreeMap<Box<String>, Box<String>>
}
#[derive(RustcDecodable, Debug)]
pub struct Edge {
	pub labels: Vec<String>
}

#[derive(RustcDecodable, Debug)]
pub struct Graph {
	pub nodes: BTreeMap<NodeIndex, Node>,
	pub edges: BTreeMap<NodeIndex, BTreeMap<NodeIndex, Edge>>
}

//#[derive(Eq, Hash, TotalEq, RustcDecodable, RustcEncodable)]
pub type NodeIndex = usize;

/***********************/
/*** Implementations ***/
/***********************/

/*** Node ***/

/// Used to give a string representation for Node
impl fmt::Display for Node {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		try!(write!(f, "Node<id={}, props=", self.id));
		for (k, v) in self.props.iter() {
			try!(write!(f, "{}, {}", k, v));
		}
		write!(f, ">")
	}
}

/// Used to convert a Node to JSON
impl ToJson for Node {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		let mut props = BTreeMap::new();
		d.insert("id".to_owned(), self.id.to_json());
		for (&ref k, &ref v) in self.props.iter() {
			props.insert(*k.clone(), Json::String(*v.clone()));
		}
		d.insert("props".to_owned(), Json::Object(props));
		Json::Object(d)
	}
}

impl ToJson for Edge {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		d.insert("labels".to_string(), Json::Array(self.labels.iter().map(|l| Json::String(l.to_string())).collect()));
		Json::Object(d)
	}
}

impl ToJson for Graph {
	fn to_json(&self) -> Json {
		let mut d = BTreeMap::new();
		let mut edge_json_map = BTreeMap::new();
		d.insert("nodes".to_string(), Json::Object(self.nodes.iter().map(|(i, n)| (i.to_string(), n.to_json())).collect()));
		for (index, edge) in self.edges.iter() {
			edge_json_map.insert(index.to_string(), Json::Object(edge.iter().map(|(i, n)| (i.to_string(), n.to_json())).collect()));
		}
		d.insert("edges".to_string(), Json::Object(edge_json_map));
		Json::Object(d)
	}
}

/*** Edge ***/

/// Used to give a string representation for Edge
impl fmt::Display for Edge {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Edge<labels={}>", self.labels.join(","))
	}
}

impl cmp::PartialEq for Edge {
	fn eq(&self, other: &Edge) -> bool {
		self.labels == other.labels
	}
}

/*** Graph ***/

/// Used to give a string representation for Graph
// impl fmt::Display for Graph {
// 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 		write!(f.buf, "Graph (\n\tnodes = {}\n\tedges = {}\n)", self.nodes, self.edges)
// 	}
// }

impl Graph {

	/// Creates a new graph with empty BTreeMaps
	pub fn new() -> Graph {
		Graph { nodes: BTreeMap::new(), edges: BTreeMap::new() }
	}

	/// Encode and decode from file

	pub fn read_from_file(name: String) -> Graph {
		let mut contents = String::new();
		let mut file:File = File::open(name).unwrap();

		file.read_to_string(&mut contents).unwrap();
		let jsonstring = match Json::from_str(&contents) {
			Ok(a) => a,
			Err(e) => panic!("Error reading JSON string: {}", e)
		};

		let mut decoder = Decoder::new(jsonstring);
		match Decodable::decode(&mut decoder) {
			Ok(x) => x,
			Err(e) => panic!("Could not decode to graph: {}", e)
		}
	}

	pub fn write_to_file(&self, name: &'static str) -> Result<usize> {
		let mut file = try!(File::create(name));
		file.write(self.to_json().to_string().into_bytes().as_slice())
	}

	/*******************/
	/****** Nodes ******/
	/*******************/

	/// Gets the next node index
	pub fn next_node_index(&self) -> NodeIndex {
		self.nodes.len() + 1
	}

	/// Adds a Node to the Graph with a vector of attributes and a BTreeMap of properties
	pub fn add_node(&mut self, attr: &[&str], props: BTreeMap<Box<String>, Box<String>>) -> NodeIndex {
		let idx = self.next_node_index();
		self.nodes.insert(idx, Node { id: idx, props: props });
		// TODO This is weird
		for a in attr.iter() {
			self.add_edge(idx, idx, a.to_string());
		}
		idx
	}

	/// Removes a Node from the Graph given a NodeIndex
	pub fn remove_node(&mut self, idx: NodeIndex) -> Option<Node> {
		// TODO should also remove the attached edges
		match self.nodes.remove(&idx) {
			Some(n) => Some(n),
			None => None
		}
	}

	/// Get Nodes with a given attribute
	pub fn nodes_with_attr<'a>(&'a self, attr: &String) -> Vec<&Node> {
		self.nodes.values().filter(|node|
			if let Some(e) = self.edges.get(&node.id) {
				if let Some(edge) = e.get(&node.id) {
					edge.labels.contains(attr)
				} else {
					false
				}
			}
			else {
				false
			}).collect()
	}

	/// Get Nodes with a key-value pair
	pub fn nodes_with_prop<'a>(&'a self, key: &String, value: &String) -> Vec<&Node> {
		self.nodes.values().filter(|node|
			node.props.iter().find(|&(k, v)| **k == *key && **v == *value ).is_some()).collect()
	}

	/*******************/
	/****** Edges ******/
	/*******************/

	/// Add an Edge to the graph from the source NodeIndex to the target NodeIndex with a label
	pub fn add_edge<'a>(&'a mut self, source: NodeIndex, target: NodeIndex, label: String) -> & mut Edge {
		//map.entry(key).get().unwrap_or_else(|v| v.insert(default))
		let src_map = self.edges.entry(source).or_insert(BTreeMap::new());
		match src_map.entry(target) {
			Entry::Vacant(e) => {e.insert(Edge { labels: vec![label] });},
			Entry::Occupied(mut e) => if e.get().labels.contains(&label) { e.get_mut().labels.push(label); } else {()}
		};
		src_map.get_mut(&source).unwrap()
	}

	/// Get Edges with a given label
	pub fn edges_with_label<'a>(&'a self, label: &String) -> BTreeMap<&'a NodeIndex, BTreeMap<&'a NodeIndex, &'a Edge>> {
		let mut edges = BTreeMap::<&NodeIndex, BTreeMap<&NodeIndex, &Edge>>::new();
		for (src, map) in self.edges.iter() {
			let filtered: BTreeMap<&NodeIndex, &Edge> = map.iter().filter(|&(_idx, edge)| edge.labels.contains(label)).collect();
			if filtered.len() > 0 {
				edges.insert(src, filtered);
			}
		}
		edges
	}

	/// Get Nodes with a given label from a source NodeIndex
	pub fn edges_with_label_from<'a>(&'a self, source: NodeIndex, label: String) -> Vec<&'a Node> {
		if let Some(edge) = self.edges.get(&source) {
		edge.iter().filter_map(
			|(&idx, edge)|
				if edge.labels.contains(&label) {
					self.nodes.get(&idx)
				} else {
					None
				}).collect()
			} else {
				vec![]
			}
	}

}
<|endoftext|>


<commit_before>use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::ptr;
use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering};

use pause::pause;

pub struct Slot {
    next: AtomicPtr<AtomicBool>
}

pub struct Guard<'a, T: ?Sized + 'a> {
    lock: &'a Mutex<T>,
    slot: &'a Slot
}

pub struct Mutex<T: ?Sized> {
    queue: AtomicPtr<Slot>,
    data: UnsafeCell<T>
}

unsafe impl<T: Send> Sync for Mutex<T> { }
unsafe impl<T: Send> Send for Mutex<T> { }

impl Slot {
    pub const fn new() -> Slot {
        Slot {
            next: AtomicPtr::new(ptr::null_mut())
        }
    }
}

impl<T> Mutex<T> {
    pub const fn new(value: T) -> Mutex<T> {
        Mutex {
            queue: AtomicPtr::new(ptr::null_mut()),
            data: UnsafeCell::new(value)
        }
    }

    pub fn into_inner(self) -> T {
        unsafe {
            self.data.into_inner()
        }
    }
}

impl<T: ?Sized> Mutex<T> {
    pub fn try_lock<'a>(&'a self, slot: &'a mut Slot) -> Option<Guard<'a, T>> {
        slot.next = AtomicPtr::new(ptr::null_mut());

        if self.queue.compare_and_swap(ptr::null_mut(), slot, Ordering::SeqCst).is_null() {
            Some(Guard {
                lock: self,
                slot: slot
            })
        } else {
            None
        }
    }

    pub fn lock<'a>(&'a self, slot: &'a mut Slot) -> Guard<'a, T> {
        slot.next = AtomicPtr::new(ptr::null_mut());
        let pred = self.queue.swap(slot, Ordering::SeqCst);
        if !pred.is_null() {
            let pred = unsafe { &*pred };
            let locked = AtomicBool::new(true);
            pred.next.store(&locked as *const _ as *mut _, Ordering::SeqCst);
            while locked.load(Ordering::SeqCst) {
                pause();
            }
        }

        Guard {
            lock: self,
            slot: slot
        }
    }

    pub fn get_mut(&mut self) -> &mut T {
        unsafe { &mut *self.data.get() }
    }
}

impl<'a, T: ?Sized> Deref for Guard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { &*self.lock.data.get() }
    }
}

impl<'a, T: ?Sized> DerefMut for Guard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.data.get() }
    }
}

impl<'a, T: ?Sized> Drop for Guard<'a, T> {
    #[unsafe_destructor_blind_to_params]
    fn drop(&mut self) {
        let succ = self.slot.next.load(Ordering::SeqCst);
        if succ.is_null() {
            let slot_ptr = self.slot as *const _ as *mut _;
            if self.lock.queue.compare_and_swap(slot_ptr, ptr::null_mut(), Ordering::SeqCst) != slot_ptr {
                let mut succ;
                loop {
                    succ = self.slot.next.load(Ordering::SeqCst);
                    if !succ.is_null() {
                        break;
                    }
                    pause();
                }
                let succ = unsafe { &*succ };
                succ.store(false, Ordering::SeqCst);
            }
        } else {
            let succ = unsafe { &*succ };
            succ.store(false, Ordering::SeqCst);
        }
    }
}

#[cfg(test)]
mod test {
    extern crate std;

    use super::{Mutex, Slot};

    // Mostly stoled from the Rust standard Mutex implementation's tests, so

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

    use self::std::sync::Arc;
    use self::std::sync::mpsc::channel;
    use self::std::sync::atomic::{AtomicUsize, Ordering};
    use self::std::thread;

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    #[test]
    fn smoke() {
        let mut slot = Slot::new();
        let m = Mutex::new(());
        drop(m.lock(&mut slot));
        drop(m.lock(&mut slot));
    }

    #[test]
    fn lots_and_lots() {
        static LOCK: Mutex<u32> = Mutex::new(0);
        const ITERS: u32 = 1000;
        const CONCURRENCY: u32 = 3;

        fn inc() {
            let mut slot = Slot::new();
            for _ in 0..ITERS {
                let mut g = LOCK.lock(&mut slot);
                *g += 1;
            }
        };

        let (tx, rx) = channel();
        for _ in 0..CONCURRENCY {
            let tx2 = tx.clone();
            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
            let tx2 = tx.clone();
            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
        }

        drop(tx);
        for _ in 0..2 * CONCURRENCY {
            rx.recv().unwrap();
        }
        let mut slot = Slot::new();
        assert_eq!(*LOCK.lock(&mut slot), ITERS * CONCURRENCY * 2);
    }

    #[test]
    fn try_lock() {
        let mut slot = Slot::new();
        let m = Mutex::new(());
        *m.try_lock(&mut slot).unwrap() = ();
    }

    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut() = NonCopy(20);
        assert_eq!(m.into_inner(), NonCopy(20));
    }

    #[test]
    fn test_lock_arc_nested() {
        // Tests nested locks and access
        // to underlying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move|| {
            let mut slot1 = Slot::new();
            let mut slot2 = Slot::new();

            let lock = arc2.lock(&mut slot1);
            let lock2 = lock.lock(&mut slot2);
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_lock_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move|| -> () {
            struct Unwinder {
                i: Arc<Mutex<i32>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    let mut slot = Slot::new();
                    *self.i.lock(&mut slot) += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
        }).join();
        let mut slot = Slot::new();
        let lock = arc.lock(&mut slot);
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_lock_unsized() {
        let mut slot = Slot::new();
        let lock: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *lock.lock(&mut slot);
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*lock.lock(&mut slot), comp);
    }
}
<commit_msg>Loosen the memory orderings<commit_after>use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::ptr;
use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering, fence};

use pause::pause;

pub struct Slot {
    next: AtomicPtr<AtomicBool>
}

pub struct Guard<'a, T: ?Sized + 'a> {
    lock: &'a Mutex<T>,
    slot: &'a Slot
}

pub struct Mutex<T: ?Sized> {
    queue: AtomicPtr<Slot>,
    data: UnsafeCell<T>
}

unsafe impl<T: Send> Sync for Mutex<T> { }
unsafe impl<T: Send> Send for Mutex<T> { }

impl Slot {
    pub const fn new() -> Slot {
        Slot {
            next: AtomicPtr::new(ptr::null_mut())
        }
    }
}

impl<T> Mutex<T> {
    pub const fn new(value: T) -> Mutex<T> {
        Mutex {
            queue: AtomicPtr::new(ptr::null_mut()),
            data: UnsafeCell::new(value)
        }
    }

    pub fn into_inner(self) -> T {
        unsafe {
            self.data.into_inner()
        }
    }
}

impl<T: ?Sized> Mutex<T> {
    pub fn try_lock<'a>(&'a self, slot: &'a mut Slot) -> Option<Guard<'a, T>> {
        slot.next = AtomicPtr::new(ptr::null_mut());

        if self.queue.compare_and_swap(ptr::null_mut(), slot, Ordering::AcqRel).is_null() {
            Some(Guard {
                lock: self,
                slot: slot
            })
        } else {
            None
        }
    }

    pub fn lock<'a>(&'a self, slot: &'a mut Slot) -> Guard<'a, T> {
        slot.next = AtomicPtr::new(ptr::null_mut());
        let pred = self.queue.swap(slot, Ordering::AcqRel);
        if !pred.is_null() {
            let pred = unsafe { &*pred };
            let locked = AtomicBool::new(true);
            pred.next.store(&locked as *const _ as *mut _, Ordering::Release);
            while locked.load(Ordering::Relaxed) {
                pause();
            }
            fence(Ordering::Acquire);
        }

        Guard {
            lock: self,
            slot: slot
        }
    }

    pub fn get_mut(&mut self) -> &mut T {
        unsafe { &mut *self.data.get() }
    }
}

impl<'a, T: ?Sized> Deref for Guard<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { &*self.lock.data.get() }
    }
}

impl<'a, T: ?Sized> DerefMut for Guard<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.data.get() }
    }
}

impl<'a, T: ?Sized> Drop for Guard<'a, T> {
    #[unsafe_destructor_blind_to_params]
    fn drop(&mut self) {
        let succ = self.slot.next.load(Ordering::Relaxed);
        if succ.is_null() {
            let slot_ptr = self.slot as *const _ as *mut _;
            if self.lock.queue.compare_and_swap(slot_ptr, ptr::null_mut(), Ordering::Release) != slot_ptr {
                let mut succ;
                loop {
                    succ = self.slot.next.load(Ordering::Relaxed);
                    if !succ.is_null() {
                        break;
                    }
                    pause();
                }
                fence(Ordering::Acquire);
                let succ = unsafe { &*succ };
                succ.store(false, Ordering::Release);
            }
        } else {
            fence(Ordering::Acquire);
            let succ = unsafe { &*succ };
            succ.store(false, Ordering::Release);
        }
    }
}

#[cfg(test)]
mod test {
    extern crate std;

    use super::{Mutex, Slot};

    // Mostly stoled from the Rust standard Mutex implementation's tests, so

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

    use self::std::sync::Arc;
    use self::std::sync::mpsc::channel;
    use self::std::sync::atomic::{AtomicUsize, Ordering};
    use self::std::thread;

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    #[test]
    fn smoke() {
        let mut slot = Slot::new();
        let m = Mutex::new(());
        drop(m.lock(&mut slot));
        drop(m.lock(&mut slot));
    }

    #[test]
    fn lots_and_lots() {
        static LOCK: Mutex<u32> = Mutex::new(0);
        const ITERS: u32 = 1000;
        const CONCURRENCY: u32 = 3;

        fn inc() {
            let mut slot = Slot::new();
            for _ in 0..ITERS {
                let mut g = LOCK.lock(&mut slot);
                *g += 1;
            }
        };

        let (tx, rx) = channel();
        for _ in 0..CONCURRENCY {
            let tx2 = tx.clone();
            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
            let tx2 = tx.clone();
            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
        }

        drop(tx);
        for _ in 0..2 * CONCURRENCY {
            rx.recv().unwrap();
        }
        let mut slot = Slot::new();
        assert_eq!(*LOCK.lock(&mut slot), ITERS * CONCURRENCY * 2);
    }

    #[test]
    fn try_lock() {
        let mut slot = Slot::new();
        let m = Mutex::new(());
        *m.try_lock(&mut slot).unwrap() = ();
    }

    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut() = NonCopy(20);
        assert_eq!(m.into_inner(), NonCopy(20));
    }

    #[test]
    fn test_lock_arc_nested() {
        // Tests nested locks and access
        // to underlying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move|| {
            let mut slot1 = Slot::new();
            let mut slot2 = Slot::new();

            let lock = arc2.lock(&mut slot1);
            let lock2 = lock.lock(&mut slot2);
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_lock_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move|| -> () {
            struct Unwinder {
                i: Arc<Mutex<i32>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    let mut slot = Slot::new();
                    *self.i.lock(&mut slot) += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
        }).join();
        let mut slot = Slot::new();
        let lock = arc.lock(&mut slot);
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_lock_unsized() {
        let mut slot = Slot::new();
        let lock: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *lock.lock(&mut slot);
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*lock.lock(&mut slot), comp);
    }
}
<|endoftext|>


<commit_before>use rand::Rng;

use super::Point;

/// A `Size` represents a region in space
#[derive(Clone, Copy, Default)]
pub struct Size {
    pub width: f32,
    pub height: f32,
}

impl Size {
    /// Returns a new `Size` of the given dimensions
    pub fn new(width: f32, height: f32) -> Size {
        Size {
            width: width,
            height: height,
        }
    }

    /// Returns true if the `Point` is contained in this `Size` or false otherwise
    pub fn _contains(&self, point: Point) -> bool {
        0.0 <= point.x && point.x <= self.width && 0.0 <= point.y && point.y <= self.height
    }

    /// Returns a random x coordinate within the bounds of this `Size`
    pub fn random_x<R: Rng>(&self, rng: &mut R) -> f32 {
        rng.gen_range(0.0, self.width)
    }

    /// Returns a random y coordinate within the bounds of this `Size`
    pub fn random_y<R: Rng>(&self, rng: &mut R) -> f32 {
        rng.gen_range(0.0, self.height)
    }
}
<commit_msg>Remove unused function `contains`<commit_after>use rand::Rng;

/// A `Size` represents a region in space
#[derive(Clone, Copy, Default)]
pub struct Size {
    pub width: f32,
    pub height: f32,
}

impl Size {
    /// Returns a new `Size` of the given dimensions
    pub fn new(width: f32, height: f32) -> Size {
        Size {
            width: width,
            height: height,
        }
    }

    /// Returns a random x coordinate within the bounds of this `Size`
    pub fn random_x<R: Rng>(&self, rng: &mut R) -> f32 {
        rng.gen_range(0.0, self.width)
    }

    /// Returns a random y coordinate within the bounds of this `Size`
    pub fn random_y<R: Rng>(&self, rng: &mut R) -> f32 {
        rng.gen_range(0.0, self.height)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::Term;
use unicode_xid::UnicodeXID;

use proc_macro2::Span;

/// A word of Rust code, such as a keyword or variable name.
///
/// An identifier consists of at least one Unicode code point, the first of
/// which has the XID_Start property and the rest of which have the XID_Continue
/// property. An underscore may be used as the first character as long as it is
/// not the only character.
///
/// - The empty string is not an identifier. Use `Option<Ident>`.
/// - An underscore by itself is not an identifier. Use
///   `Token![_]` instead.
/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
///
/// An identifier constructed with `Ident::new` is permitted to be a Rust
/// keyword, though parsing one through its [`Synom`] implementation rejects
/// Rust keywords.
///
/// [`Synom`]: synom/trait.Synom.html
///
/// # Examples
///
/// A new ident can be created from a string using the `Ident::from` function.
///
/// ```rust
/// extern crate syn;
/// use syn::Ident;
/// #
/// # fn main() {
///
/// let ident = Ident::from("another_identifier");
///
/// # }
/// ```
///
/// When the ident is used in Macros 1.1 output, it needs to be turned into
/// a token stream. This is easy to do using the `quote!` macro from the `quote`
/// crate.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// # extern crate syn;
/// # use syn::Ident;
/// # fn main() {
/// # let ident = Ident::from("another_identifier");
/// #
/// // Create tokens using the ident.
/// let expanded = quote! { let #ident = 10; };
///
/// // Derive a new ident from the existing one.
/// let temp_ident = Ident::from(format!("new_{}", ident));
/// let expanded = quote! { let $temp_ident = 10; };
///
/// # }
/// ```
///
/// If `syn` is used to parse existing Rust source code, it is often useful to
/// convert the `Ident` to a more generic string data type at some point. The
/// methods `as_ref()` and `to_string()` achieve this.
///
/// ```rust
/// # use syn::Ident;
/// # let ident = Ident::from("another_identifier");
/// #
/// // Examine the ident as a &str.
/// let ident_str = ident.as_ref();
/// if ident_str.len() > 60 {
///     println!("Very long identifier: {}", ident_str)
/// }
///
/// // Create a String from the ident.
/// let ident_string = ident.to_string();
/// give_away(ident_string);
///
/// fn give_away(s: String) { /* ... */ }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Ident {
    term: Term,
    pub span: Span,
}

impl Ident {
    /// Creates a new `Ident` from the structured items. This is mainly used
    /// by the parser to create `Ident`s from existing Rust source code.
    ///
    /// Creating new `Ident`s programmatically is easier with `Ident::from`.
    pub fn new(s: &str, span: Span) -> Self {
        if s.is_empty() {
            panic!("ident is not allowed to be empty; use Option<Ident>");
        }

        if s.starts_with('\'') {
            panic!("ident is not allowed to be a lifetime; use syn::Lifetime");
        }

        if s == "_" {
            panic!("`_` is not a valid ident; use syn::token::Underscore");
        }

        if s.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
            panic!("ident cannot be a number, use syn::Index instead");
        }

        fn xid_ok(s: &str) -> bool {
            let mut chars = s.chars();
            let first = chars.next().unwrap();
            if !(UnicodeXID::is_xid_start(first) || first == '_') {
                return false;
            }
            for ch in chars {
                if !UnicodeXID::is_xid_continue(ch) {
                    return false;
                }
            }
            true
        }

        if !xid_ok(s) {
            panic!("{:?} is not a valid ident", s);
        }

        Ident {
            term: Term::intern(s),
            span: span,
        }
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident::new(s, Span::def_site())
    }
}

impl From<Token![self]> for Ident {
    fn from(tok: Token![self]) -> Self {
        Ident::new("self", tok.0)
    }
}

impl From<Token![Self]> for Ident {
    fn from(tok: Token![Self]) -> Self {
        Ident::new("Self", tok.0)
    }
}

impl From<Token![super]> for Ident {
    fn from(tok: Token![super]) -> Self {
        Ident::new("super", tok.0)
    }
}

impl From<Token![crate]> for Ident {
    fn from(tok: Token![crate]) -> Self {
        Ident::new("crate", tok.0)
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident::new(&s, Span::def_site())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident::new(&s, Span::def_site())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        self.term.as_str()
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.term.as_str().fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
where
    T: AsRef<str>,
{
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl Eq for Ident {}

impl PartialOrd for Ident {
    fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Ident {
    fn cmp(&self, other: &Ident) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl Hash for Ident {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.as_ref().hash(h);
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use synom::Synom;
    use buffer::Cursor;
    use parse_error;
    use synom::PResult;

    impl Synom for Ident {
        fn parse(input: Cursor) -> PResult<Self> {
            let (span, term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }
            match term.as_str() {
                // From https://doc.rust-lang.org/grammar.html#keywords
                "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const"
                | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
                | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
                | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub"
                | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
                | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
                | "virtual" | "where" | "while" | "yield" => return parse_error(),
                _ => {}
            }

            Ok((
                Ident {
                    span: span,
                    term: term,
                },
                rest,
            ))
        }

        fn description() -> Option<&'static str> {
            Some("identifier")
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{ToTokens, Tokens};
    use proc_macro2::{TokenNode, TokenTree};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(TokenTree {
                span: self.span,
                kind: TokenNode::Term(self.term),
            })
        }
    }
}
<commit_msg>Touch up Ident documentation<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::Term;
use unicode_xid::UnicodeXID;

use proc_macro2::Span;

/// A word of Rust code, which may be a keyword or legal variable name.
///
/// An identifier consists of at least one Unicode code point, the first of
/// which has the XID_Start property and the rest of which have the XID_Continue
/// property. An underscore may be used as the first character as long as it is
/// not the only character.
///
/// - The empty string is not an identifier. Use `Option<Ident>`.
/// - An underscore by itself is not an identifier. Use
///   `Token![_]` instead.
/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
///
/// An identifier constructed with `Ident::new` is permitted to be a Rust
/// keyword, though parsing one through its [`Synom`] implementation rejects
/// Rust keywords.
///
/// [`Synom`]: synom/trait.Synom.html
///
/// # Examples
///
/// A new ident can be created from a string using the `Ident::from` function.
/// Idents produced by `Ident::from` are set to resolve at the procedural macro
/// *def site* by default. A different span can be provided explicitly by using
/// `Ident::new`.
///
/// ```rust
/// extern crate syn;
/// extern crate proc_macro2;
///
/// use syn::Ident;
/// use proc_macro2::Span;
///
/// fn main() {
///     let def_ident = Ident::from("definitely");
///     let call_ident = Ident::new("calligraphy", Span::call_site());
///
///     println!("{} {}", def_ident, call_ident);
/// }
/// ```
///
/// An ident can be interpolated into a token stream using the `quote!` macro.
///
/// ```rust
/// #[macro_use]
/// extern crate quote;
///
/// extern crate syn;
/// use syn::Ident;
///
/// fn main() {
///     let ident = Ident::from("demo");
///
///     // Create a variable binding whose name is this ident.
///     let expanded = quote! { let #ident = 10; };
///
///     // Create a variable binding with a slightly different name.
///     let temp_ident = Ident::from(format!("new_{}", ident));
///     let expanded = quote! { let #temp_ident = 10; };
/// }
/// ```
///
/// A string representation of the ident is available through the `as_ref()` and
/// `to_string()` methods.
///
/// ```rust
/// # use syn::Ident;
/// # let ident = Ident::from("another_identifier");
/// #
/// // Examine the ident as a &str.
/// let ident_str = ident.as_ref();
/// if ident_str.len() > 60 {
///     println!("Very long identifier: {}", ident_str)
/// }
///
/// // Create a String from the ident.
/// let ident_string = ident.to_string();
/// give_away(ident_string);
///
/// fn give_away(s: String) { /* ... */ }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Ident {
    term: Term,
    pub span: Span,
}

impl Ident {
    /// Creates an ident with the given string representation.
    ///
    /// # Panics
    ///
    /// Panics if the input string is neither a keyword nor a legal variable
    /// name.
    pub fn new(s: &str, span: Span) -> Self {
        if s.is_empty() {
            panic!("ident is not allowed to be empty; use Option<Ident>");
        }

        if s.starts_with('\'') {
            panic!("ident is not allowed to be a lifetime; use syn::Lifetime");
        }

        if s == "_" {
            panic!("`_` is not a valid ident; use syn::token::Underscore");
        }

        if s.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
            panic!("ident cannot be a number, use syn::Index instead");
        }

        fn xid_ok(s: &str) -> bool {
            let mut chars = s.chars();
            let first = chars.next().unwrap();
            if !(UnicodeXID::is_xid_start(first) || first == '_') {
                return false;
            }
            for ch in chars {
                if !UnicodeXID::is_xid_continue(ch) {
                    return false;
                }
            }
            true
        }

        if !xid_ok(s) {
            panic!("{:?} is not a valid ident", s);
        }

        Ident {
            term: Term::intern(s),
            span: span,
        }
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident::new(s, Span::def_site())
    }
}

impl From<Token![self]> for Ident {
    fn from(tok: Token![self]) -> Self {
        Ident::new("self", tok.0)
    }
}

impl From<Token![Self]> for Ident {
    fn from(tok: Token![Self]) -> Self {
        Ident::new("Self", tok.0)
    }
}

impl From<Token![super]> for Ident {
    fn from(tok: Token![super]) -> Self {
        Ident::new("super", tok.0)
    }
}

impl From<Token![crate]> for Ident {
    fn from(tok: Token![crate]) -> Self {
        Ident::new("crate", tok.0)
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident::new(&s, Span::def_site())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident::new(&s, Span::def_site())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        self.term.as_str()
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.term.as_str().fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
where
    T: AsRef<str>,
{
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl Eq for Ident {}

impl PartialOrd for Ident {
    fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Ident {
    fn cmp(&self, other: &Ident) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl Hash for Ident {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.as_ref().hash(h);
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use synom::Synom;
    use buffer::Cursor;
    use parse_error;
    use synom::PResult;

    impl Synom for Ident {
        fn parse(input: Cursor) -> PResult<Self> {
            let (span, term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }
            match term.as_str() {
                // From https://doc.rust-lang.org/grammar.html#keywords
                "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const"
                | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
                | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
                | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub"
                | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
                | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
                | "virtual" | "where" | "while" | "yield" => return parse_error(),
                _ => {}
            }

            Ok((
                Ident {
                    span: span,
                    term: term,
                },
                rest,
            ))
        }

        fn description() -> Option<&'static str> {
            Some("identifier")
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{ToTokens, Tokens};
    use proc_macro2::{TokenNode, TokenTree};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(TokenTree {
                span: self.span,
                kind: TokenNode::Term(self.term),
            })
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// 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.

//! Local state for keys in the snapshot in progress (the "index").

use blob;
use hash;
use util;
use super::schema;

use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;

use time::Duration;

use periodic_timer::PeriodicTimer;
use process::{Process, MsgHandler};

#[derive(Clone, Debug)]
pub struct Entry {
    pub id: Option<u64>,
    pub parent_id: Option<u64>,

    pub name: Vec<u8>,

    pub created: Option<i64>,
    pub modified: Option<i64>,
    pub accessed: Option<i64>,

    pub permissions: Option<u64>,
    pub user_id: Option<u64>,
    pub group_id: Option<u64>,

    pub data_hash: Option<Vec<u8>>,
    pub data_length: Option<u64>,
}

pub type IndexProcess = Process<Msg, Reply>;

pub enum Msg {
    /// Insert an entry in the key index.
    /// Returns `Id` with the new entry ID.
    Insert(Entry),

    /// Lookup an entry in the key index by its parent id and name.
    /// Returns either `Entry` with the found entry or `NotFound`.
    Lookup(Option<u64>, Vec<u8>),

    /// Update the `payload` and `persistent_ref` of an entry.
    /// Returns `UpdateOk`.
    UpdateDataHash(Entry, Option<hash::Hash>, Option<blob::ChunkRef>),

    /// List a directory (aka. `level`) in the index.
    /// Returns `ListResult` with all the entries under the given parent.
    ListDir(Option<u64>),

    /// Flush this key index.
    Flush,
}

pub enum Reply {
    Entry(Entry),
    NotFound,
    UpdateOk,
    ListResult(Vec<(Entry, Option<blob::ChunkRef>)>),
    FlushOk,
}

pub struct Index {
    path: String,
    conn: SqliteConnection,
    flush_timer: PeriodicTimer,
}

fn i64_to_u64_or_panic(x: i64) -> u64 {
    if x < 0 {
        panic!("expected u64, got {:?}", x);
    }
    return x as u64;
}

impl Index {
    pub fn new(path: String) -> Index {
        let conn = SqliteConnection::establish(&path).expect("Could not open SQLite database");

        let ki = Index {
            path: path,
            conn: conn,
            flush_timer: PeriodicTimer::new(Duration::seconds(5)),
        };

        let dir = diesel::migrations::find_migrations_directory().unwrap();
        diesel::migrations::run_pending_migrations_in_directory(&ki.conn,
                                                                &dir,
                                                                &mut util::InfoWriter)
            .unwrap();
        ki.conn.begin_transaction().unwrap();

        ki
    }

    #[cfg(test)]
    pub fn new_for_testing() -> Index {
        Index::new(":memory:".to_string())
    }

    fn last_insert_rowid(&self) -> i64 {
        diesel::select(diesel::expression::sql("last_insert_rowid()"))
            .first::<i64>(&self.conn)
            .unwrap()
    }

    pub fn maybe_flush(&mut self) {
        if self.flush_timer.did_fire() {
            self.flush();
        }
    }

    pub fn flush(&mut self) {
        self.conn.commit_transaction().unwrap();
        self.conn.begin_transaction().unwrap();
    }
}

impl Clone for Index {
    fn clone(&self) -> Index {
        Index::new(self.path.clone())
    }
}

impl MsgHandler<Msg, Reply> for Index {
    fn handle(&mut self, msg: Msg, reply: Box<Fn(Reply)>) {
        match msg {

            Msg::Insert(entry) => {
                use super::schema::keys::dsl::*;

                let entry = match entry.id {
                    Some(id_) => {
                        // Replace existing entry.
                        diesel::update(keys.find(id_ as i64))
                            .set((parent.eq(entry.parent_id.map(|x| x as i64)),
                                  name.eq(&entry.name[..]),
                                  created.eq(entry.created),
                                  modified.eq(entry.modified),
                                  accessed.eq(entry.accessed)))
                            .execute(&self.conn)
                            .expect("Error updating key");
                        entry
                    }
                    None => {
                        // Insert new entry.
                        {
                            let new = schema::NewKey {
                                parent: entry.parent_id.map(|x| x as i64),
                                name: &entry.name[..],
                                created: entry.created,
                                modified: entry.modified,
                                accessed: entry.accessed,
                                permissions: entry.permissions.map(|x| x as i64),
                                group_id: entry.group_id.map(|x| x as i64),
                                user_id: entry.user_id.map(|x| x as i64),
                                hash: None,
                                persistent_ref: None,
                            };

                            diesel::insert(&new)
                                .into(keys)
                                .execute(&self.conn)
                                .expect("Error inserting key");
                        }
                        let mut entry = entry;
                        entry.id = Some(self.last_insert_rowid() as u64);
                        entry
                    }
                };

                return reply(Reply::Entry(entry));
            }

            Msg::Lookup(parent_, name_) => {
                use super::schema::keys::dsl::*;

                let row_opt = keys.filter(parent.eq(parent_.map(|x| x as i64)))
                                  .filter(name.eq(&name_[..]))
                                  .first::<schema::Key>(&self.conn)
                                  .optional()
                                  .expect("Error searching keys");

                if let Some(row) = row_opt {
                    return reply(Reply::Entry(Entry {
                        id: Some(row.id as u64),
                        parent_id: parent_,
                        name: name_,
                        created: row.created,
                        modified: row.modified,
                        accessed: row.accessed,
                        permissions: row.permissions.map(|x| x as u64),
                        user_id: row.user_id.map(|x| x as u64),
                        group_id: row.group_id.map(|x| x as u64),
                        data_hash: row.hash,
                        data_length: None,
                    }));
                } else {
                    return reply(Reply::NotFound);
                }
            }

            Msg::UpdateDataHash(entry, hash_opt, persistent_ref_opt) => {
                use super::schema::keys::dsl::*;

                let id_ = entry.id.expect("Tried to update without an id") as i64;
                assert!(hash_opt.is_some() == persistent_ref_opt.is_some());

                let hash_bytes = hash_opt.map(|h| h.bytes);
                let persistent_ref_bytes = persistent_ref_opt.map(|p| p.as_bytes());

                if entry.modified.is_some() {
                    diesel::update(keys.find(id_)
                                       .filter(modified.eq::<Option<i64>>(None)
                                                       .or(modified.le(entry.modified))))
                        .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                        .execute(&self.conn)
                        .expect("Error updating key");
                } else {
                    diesel::update(keys.find(id_))
                        .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                        .execute(&self.conn)
                        .expect("Error updating key");
                }

                self.maybe_flush();
                return reply(Reply::UpdateOk);
            }

            Msg::Flush => {
                self.flush();
                return reply(Reply::FlushOk);
            }

            Msg::ListDir(parent_opt) => {
                use super::schema::keys::dsl::*;

                let rows = keys.filter(parent.eq(parent_opt.map(|x| x as i64)))
                               .load::<schema::Key>(&self.conn)
                               .expect("Error listing keys");

                return reply(Reply::ListResult(rows.into_iter()
                                                   .map(|mut r| {
                                                       (Entry {
                                                           id: Some(r.id as u64),
                                                           parent_id: r.parent.map(|x| x as u64),
                                                           name: r.name,
                                                           created: r.created,
                                                           modified: r.modified,
                                                           accessed: r.accessed,
                                                           permissions: r.permissions
                                                                         .map(|x| x as u64),
                                                           user_id: r.user_id.map(|x| x as u64),
                                                           group_id: r.group_id.map(|x| x as u64),
                                                           data_hash: r.hash,
                                                           data_length: None,
                                                       },
                                                        r.persistent_ref.as_mut().map(|p| {
                                                           blob::ChunkRef::from_bytes(&mut &p[..])
                                                               .unwrap()
                                                       }))
                                                   })
                                                   .collect()));
            }
        }
    }
}
<commit_msg>Correct filtering when NULL is involved.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// 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.

//! Local state for keys in the snapshot in progress (the "index").

use blob;
use hash;
use util;
use super::schema;

use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;

use time::Duration;

use periodic_timer::PeriodicTimer;
use process::{Process, MsgHandler};

#[derive(Clone, Debug)]
pub struct Entry {
    pub id: Option<u64>,
    pub parent_id: Option<u64>,

    pub name: Vec<u8>,

    pub created: Option<i64>,
    pub modified: Option<i64>,
    pub accessed: Option<i64>,

    pub permissions: Option<u64>,
    pub user_id: Option<u64>,
    pub group_id: Option<u64>,

    pub data_hash: Option<Vec<u8>>,
    pub data_length: Option<u64>,
}

pub type IndexProcess = Process<Msg, Reply>;

pub enum Msg {
    /// Insert an entry in the key index.
    /// Returns `Id` with the new entry ID.
    Insert(Entry),

    /// Lookup an entry in the key index by its parent id and name.
    /// Returns either `Entry` with the found entry or `NotFound`.
    Lookup(Option<u64>, Vec<u8>),

    /// Update the `payload` and `persistent_ref` of an entry.
    /// Returns `UpdateOk`.
    UpdateDataHash(Entry, Option<hash::Hash>, Option<blob::ChunkRef>),

    /// List a directory (aka. `level`) in the index.
    /// Returns `ListResult` with all the entries under the given parent.
    ListDir(Option<u64>),

    /// Flush this key index.
    Flush,
}

pub enum Reply {
    Entry(Entry),
    NotFound,
    UpdateOk,
    ListResult(Vec<(Entry, Option<blob::ChunkRef>)>),
    FlushOk,
}

pub struct Index {
    path: String,
    conn: SqliteConnection,
    flush_timer: PeriodicTimer,
}

fn i64_to_u64_or_panic(x: i64) -> u64 {
    if x < 0 {
        panic!("expected u64, got {:?}", x);
    }
    return x as u64;
}

impl Index {
    pub fn new(path: String) -> Index {
        let conn = SqliteConnection::establish(&path).expect("Could not open SQLite database");

        let ki = Index {
            path: path,
            conn: conn,
            flush_timer: PeriodicTimer::new(Duration::seconds(5)),
        };

        let dir = diesel::migrations::find_migrations_directory().unwrap();
        diesel::migrations::run_pending_migrations_in_directory(&ki.conn,
                                                                &dir,
                                                                &mut util::InfoWriter)
            .unwrap();
        ki.conn.begin_transaction().unwrap();

        ki
    }

    #[cfg(test)]
    pub fn new_for_testing() -> Index {
        Index::new(":memory:".to_string())
    }

    fn last_insert_rowid(&self) -> i64 {
        diesel::select(diesel::expression::sql("last_insert_rowid()"))
            .first::<i64>(&self.conn)
            .unwrap()
    }

    pub fn maybe_flush(&mut self) {
        if self.flush_timer.did_fire() {
            self.flush();
        }
    }

    pub fn flush(&mut self) {
        self.conn.commit_transaction().unwrap();
        self.conn.begin_transaction().unwrap();
    }
}

impl Clone for Index {
    fn clone(&self) -> Index {
        Index::new(self.path.clone())
    }
}

impl MsgHandler<Msg, Reply> for Index {
    fn handle(&mut self, msg: Msg, reply: Box<Fn(Reply)>) {
        match msg {

            Msg::Insert(entry) => {
                use super::schema::keys::dsl::*;

                let entry = match entry.id {
                    Some(id_) => {
                        // Replace existing entry.
                        diesel::update(keys.find(id_ as i64))
                            .set((parent.eq(entry.parent_id.map(|x| x as i64)),
                                  name.eq(&entry.name[..]),
                                  created.eq(entry.created),
                                  modified.eq(entry.modified),
                                  accessed.eq(entry.accessed)))
                            .execute(&self.conn)
                            .expect("Error updating key");
                        entry
                    }
                    None => {
                        // Insert new entry.
                        {
                            let new = schema::NewKey {
                                parent: entry.parent_id.map(|x| x as i64),
                                name: &entry.name[..],
                                created: entry.created,
                                modified: entry.modified,
                                accessed: entry.accessed,
                                permissions: entry.permissions.map(|x| x as i64),
                                group_id: entry.group_id.map(|x| x as i64),
                                user_id: entry.user_id.map(|x| x as i64),
                                hash: None,
                                persistent_ref: None,
                            };

                            diesel::insert(&new)
                                .into(keys)
                                .execute(&self.conn)
                                .expect("Error inserting key");
                        }
                        let mut entry = entry;
                        entry.id = Some(self.last_insert_rowid() as u64);
                        entry
                    }
                };

                return reply(Reply::Entry(entry));
            }

            Msg::Lookup(parent_, name_) => {
                use super::schema::keys::dsl::*;

                let row_opt = match parent_ {
                    Some(p) => {
                        keys.filter(parent.eq(p as i64))
                            .filter(name.eq(&name_[..]))
                            .first::<schema::Key>(&self.conn)
                            .optional()
                            .expect("Error searching keys")
                    }
                    None => {
                        keys.filter(parent.is_null())
                            .filter(name.eq(&name_[..]))
                            .first::<schema::Key>(&self.conn)
                            .optional()
                            .expect("Error searching keys")
                    }
                };

                if let Some(row) = row_opt {
                    return reply(Reply::Entry(Entry {
                        id: Some(row.id as u64),
                        parent_id: parent_,
                        name: name_,
                        created: row.created,
                        modified: row.modified,
                        accessed: row.accessed,
                        permissions: row.permissions.map(|x| x as u64),
                        user_id: row.user_id.map(|x| x as u64),
                        group_id: row.group_id.map(|x| x as u64),
                        data_hash: row.hash,
                        data_length: None,
                    }));
                } else {
                    return reply(Reply::NotFound);
                }
            }

            Msg::UpdateDataHash(entry, hash_opt, persistent_ref_opt) => {
                use super::schema::keys::dsl::*;

                let id_ = entry.id.expect("Tried to update without an id") as i64;
                assert!(hash_opt.is_some() == persistent_ref_opt.is_some());

                let hash_bytes = hash_opt.map(|h| h.bytes);
                let persistent_ref_bytes = persistent_ref_opt.map(|p| p.as_bytes());

                if entry.modified.is_some() {
                    diesel::update(keys.find(id_)
                                       .filter(modified.eq::<Option<i64>>(None)
                                                       .or(modified.le(entry.modified))))
                        .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                        .execute(&self.conn)
                        .expect("Error updating key");
                } else {
                    diesel::update(keys.find(id_))
                        .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                        .execute(&self.conn)
                        .expect("Error updating key");
                }

                self.maybe_flush();
                return reply(Reply::UpdateOk);
            }

            Msg::Flush => {
                self.flush();
                return reply(Reply::FlushOk);
            }

            Msg::ListDir(parent_opt) => {
                use super::schema::keys::dsl::*;

                let rows = match parent_opt {
                    Some(p) => {
                        keys.filter(parent.eq(p as i64))
                            .load::<schema::Key>(&self.conn)
                            .expect("Error listing keys")
                    }
                    None => {
                        keys.filter(parent.is_null())
                            .load::<schema::Key>(&self.conn)
                            .expect("Error listing keys")
                    }
                };

                return reply(Reply::ListResult(rows.into_iter()
                                                   .map(|mut r| {
                                                       (Entry {
                                                           id: Some(r.id as u64),
                                                           parent_id: r.parent.map(|x| x as u64),
                                                           name: r.name,
                                                           created: r.created,
                                                           modified: r.modified,
                                                           accessed: r.accessed,
                                                           permissions: r.permissions
                                                                         .map(|x| x as u64),
                                                           user_id: r.user_id.map(|x| x as u64),
                                                           group_id: r.group_id.map(|x| x as u64),
                                                           data_hash: r.hash,
                                                           data_length: None,
                                                       },
                                                        r.persistent_ref.as_mut().map(|p| {
                                                           blob::ChunkRef::from_bytes(&mut &p[..])
                                                               .unwrap()
                                                       }))
                                                   })
                                                   .collect()));
            }
        }
    }
}
<|endoftext|>