<commit_before>use ndarray::{Axis, stack};
use std::collections::BTreeMap;
use helper::*;
use join::*;
use error::*;
use types::*;

#[derive(Debug, Clone, PartialEq)]
pub struct DataFrame {
    columns: BTreeMap<ColumnType, usize>,
    data: Matrix<InnerType>,
    index: BTreeMap<IndexType, usize>,
}

impl DataFrame {
    pub fn new(data: Matrix<f64>) -> DataFrame {
        let data: Matrix<InnerType> = data.mapv(InnerType::from);

        let columns: BTreeMap<ColumnType, usize> = (0..data.shape()[1])
            .enumerate()
            .map(|(x, y)| (ColumnType::Str(x.to_string()), y))
            .collect();

        let index: BTreeMap<IndexType, usize> = (0..data.shape()[0])
            .enumerate()
            .map(|(x, y)| (IndexType::Str(x.to_string()), y))
            .collect();

        DataFrame {
            data: data,
            columns: columns,
            index: index,
        }
    }

    pub fn columns(mut self, columns: Vec<String>) -> Result<DataFrame> {
        if columns.len() != self.data.shape()[1] {
            return Err(ErrorKind::ColumnShapeMismatch.into());
        }
        self.columns = columns.iter()
            .zip((0..columns.len()))
            .map(|(x, y)| (ColumnType::from(x.to_string()), y))
            .collect();
        Ok(self)
    }

    pub fn index(mut self, index: Vec<String>) -> Result<DataFrame> {
        if index.len() != self.data.shape()[0] {
            return Err(ErrorKind::RowShapeMismatch.into());
        }
        self.index = index.iter()
            .zip((0..index.len()))
            .map(|(x, y)| (IndexType::from(x.to_string()), y))
            .collect();
        Ok(self)
    }

    pub fn names(&self) -> Vec<ColumnType> {
        self.columns.keys().map(|x| x.to_owned()).collect()
    }

    pub fn get(self, name: &str) -> Result<Column<InnerType>> {
        let name = ColumnType::from(name.to_string());
        match self.columns.get(&name) {
            Some(x) => Ok(self.data.column(*x).to_owned()),
            None => {
                match name {
                    ColumnType::Str(z) => {
                        return Err(ErrorKind::InvalidColumnName(z.to_string()).into())
                    }
                    ColumnType::Date(z) => {
                        return Err(ErrorKind::InvalidColumnName(z.to_string()).into())
                    }
                    ColumnType::Int(z) => {
                        return Err(ErrorKind::InvalidColumnName(z.to_string()).into())
                    }
                }
            }
        }
    }

    pub fn insert_row(mut self, data: Matrix<InnerType>, index: &str) -> Result<DataFrame> {
        let index = IndexType::from(index.to_string());

        let ind_idx = {
            self.index.len()
        };
        self.index.insert(index, ind_idx);
        self.data = match stack(Axis(0), &[self.data.view(), data.view()]) {
            Ok(z) => z,
            Err(_) => return Err(ErrorKind::StackFail.into()),
        };
        Ok(self)

    }

    pub fn insert_column(mut self, data: Matrix<f64>, name: &str) -> Result<DataFrame> {
        let name = ColumnType::from(name.to_string());
        let data = data.mapv(InnerType::from);
        let columns_idx = {
            self.columns.len()
        };
        self.columns.insert(name, columns_idx);
        self.data = match stack(Axis(1), &[self.data.view(), data.view()]) {
            Ok(z) => z,
            Err(_) => return Err(ErrorKind::StackFail.into()),
        };
        Ok(self)

    }

    pub fn shape(&self) -> (usize, usize) {
        self.data.dim()
    }

    pub fn drop_row(&mut self, indexes: &[&str]) -> Result<DataFrame> {
        let mut idxs = vec![];
        let indexes: Vec<IndexType> =
            indexes.iter().map(|x| IndexType::from(x.to_string())).collect();

        let new_map: &mut BTreeMap<IndexType, usize> = &mut self.index.clone();
        for name in indexes.iter() {
            let idx = new_map.remove(name);
            idxs.push(idx.unwrap());
            for (_, y) in new_map.iter_mut() {
                if y > &mut idx.unwrap() {
                    *y -= 1;
                }
            }
        }
        let rows = self.shape().0;
        let to_keep: Vec<usize> = (0..rows).filter(|x| !idxs.iter().any(|&y| y == *x)).collect();
        Ok(DataFrame {
            data: self.data.select(Axis(0), &to_keep[..]),
            columns: self.columns.to_owned(),
            index: new_map.to_owned(),
        })
    }

    pub fn drop_column(&mut self, names: &[&str]) -> Result<DataFrame> {
        let mut idxs = vec![];
        let names: Vec<ColumnType> =
            names.iter().map(|x| ColumnType::from(x.to_string())).collect();

        let new_map: &mut BTreeMap<ColumnType, usize> = &mut self.columns.clone();
        for name in names.iter() {
            let idx = new_map.remove(name);
            idxs.push(idx.unwrap());
            for (_, y) in new_map.iter_mut() {
                if y > &mut idx.unwrap() {
                    *y -= 1;
                }
            }
        }
        let cols = self.shape().1;
        let to_keep: Vec<usize> = (0..cols).filter(|x| !idxs.iter().any(|&y| y == *x)).collect();

        Ok(DataFrame {
            data: self.data.select(Axis(1), &to_keep[..]),
            columns: new_map.to_owned(),
            index: self.index.to_owned(),
        })
    }

    pub fn concat(&self, axis: Axis, other: &DataFrame) -> Result<DataFrame> {

        match axis {
            Axis(0) => {
                if self.shape().1 == other.shape().1 {
                    let new_map: BTreeMap<ColumnType, usize> = self.columns
                        .iter()
                        .map(|(x, y)| (x.to_owned(), *y))
                        .collect();

                    let new_index: BTreeMap<IndexType, usize> = concat_index_maps(&self.index,
                                                                                &other.index);

                    let new_matrix = match stack(Axis(0), &[self.data.view(), other.data.view()]) {
                        Ok(z) => z,
                        Err(_) => return Err(ErrorKind::StackFail.into()),
                    };
                    Ok(DataFrame {
                        data: new_matrix,
                        columns: new_map,
                        index: new_index,
                    })
                } else {
                    return Err(ErrorKind::ColumnShapeMismatch.into());
                }
            }
            Axis(1) => {
                if self.shape().0 == other.shape().0 {
                    let other_map: BTreeMap<ColumnType, usize> = other.columns
                        .iter()
                        .map(|(x, y)| (x.to_owned(), y + self.columns.len()))
                        .collect();
                    let new_map: BTreeMap<ColumnType, usize> = self.columns
                        .iter()
                        .chain(other_map.iter())
                        .map(|(x, y)| (x.to_owned(), *y))
                        .collect();

                    let new_matrix = match stack(Axis(1), &[self.data.view(), other.data.view()]) {
                        Ok(z) => z,
                        Err(_) => return Err(ErrorKind::StackFail.into()),
                    };
                    Ok(DataFrame {
                        data: new_matrix,
                        columns: new_map,
                        index: self.index.to_owned(),
                    })
                } else {
                    return Err(ErrorKind::RowShapeMismatch.into());
                }
            }
            _ => return Err(ErrorKind::InvalidAxis.into()),
        }

    }
    pub fn inner_join(&self, other: &DataFrame) -> Result<DataFrame> {

        let idxs: Vec<(IndexType, usize, Option<usize>)> =
            Join::new(JoinType::InnerJoin,
                      self.index.clone().into_iter(),
                      other.index.clone())
                .collect();

        if idxs.len() == 0 {
            return Err(ErrorKind::NoCommonValues.into());
        }

        let new_matrix: Matrix<InnerType> = {
            let i1: Vec<usize> = idxs.iter().map(|&(_, x, _)| x).collect();
            let i2: Vec<usize> = idxs.iter().map(|&(_, _, y)| y.unwrap()).collect();
            let mat1 = self.data.select(Axis(0), &i1[..]);
            let mat2 = other.data.select(Axis(0), &i2[..]);
            match stack(Axis(1), &[mat1.view(), mat2.view()]) {
                Ok(z) => z,
                Err(_) => return Err(ErrorKind::StackFail.into()),
            }
        };

        Ok(DataFrame {
            data: new_matrix,
            columns: concat_column_maps(&self.columns, &other.columns),
            index: merge_maps(&self.index, &other.index),
        })
    }
}

// To implement....?
// // parallelized join
// // parallelized concatenation
// // parallelized frequency counts
// // index dataframe?
// // sample rows
// // find/select
// // sort
// // statistics (mean, median, stdev)
// // print
//
// // statistics (mean, median, stdev)
// // print
<commit_msg>reordered<commit_after>use ndarray::{Axis, stack};
use std::collections::BTreeMap;
use helper::*;
use join::*;
use error::*;
use types::*;

#[derive(Debug, Clone, PartialEq)]
pub struct DataFrame {
    columns: BTreeMap<ColumnType, usize>,
    data: Matrix<InnerType>,
    index: BTreeMap<IndexType, usize>,
}

impl DataFrame {
    pub fn new(data: Matrix<f64>) -> DataFrame {
        let data: Matrix<InnerType> = data.mapv(InnerType::from);

        let columns: BTreeMap<ColumnType, usize> = (0..data.shape()[1])
            .enumerate()
            .map(|(x, y)| (ColumnType::Str(x.to_string()), y))
            .collect();

        let index: BTreeMap<IndexType, usize> = (0..data.shape()[0])
            .enumerate()
            .map(|(x, y)| (IndexType::Str(x.to_string()), y))
            .collect();

        DataFrame {
            data: data,
            columns: columns,
            index: index,
        }
    }

    pub fn columns(mut self, columns: Vec<String>) -> Result<DataFrame> {
        if columns.len() != self.data.shape()[1] {
            return Err(ErrorKind::ColumnShapeMismatch.into());
        }
        self.columns = columns.iter()
            .zip((0..columns.len()))
            .map(|(x, y)| (ColumnType::from(x.to_string()), y))
            .collect();
        Ok(self)
    }

    pub fn index(mut self, index: Vec<String>) -> Result<DataFrame> {
        if index.len() != self.data.shape()[0] {
            return Err(ErrorKind::RowShapeMismatch.into());
        }
        self.index = index.iter()
            .zip((0..index.len()))
            .map(|(x, y)| (IndexType::from(x.to_string()), y))
            .collect();
        Ok(self)
    }

    pub fn names(&self) -> Vec<ColumnType> {
        self.columns.keys().map(|x| x.to_owned()).collect()
    }

    pub fn get(self, name: &str) -> Result<Column<InnerType>> {
        let name = ColumnType::from(name.to_string());
        match self.columns.get(&name) {
            Some(x) => Ok(self.data.column(*x).to_owned()),
            None => {
                match name {
                    ColumnType::Str(z) => {
                        return Err(ErrorKind::InvalidColumnName(z.to_string()).into())
                    }
                    ColumnType::Date(z) => {
                        return Err(ErrorKind::InvalidColumnName(z.to_string()).into())
                    }
                    ColumnType::Int(z) => {
                        return Err(ErrorKind::InvalidColumnName(z.to_string()).into())
                    }
                }
            }
        }
    }

    pub fn insert_row(mut self, data: Matrix<InnerType>, index: &str) -> Result<DataFrame> {
        let index = IndexType::from(index.to_string());

        let ind_idx = {
            self.index.len()
        };
        self.index.insert(index, ind_idx);
        self.data = match stack(Axis(0), &[self.data.view(), data.view()]) {
            Ok(z) => z,
            Err(_) => return Err(ErrorKind::StackFail.into()),
        };
        Ok(self)

    }

    pub fn shape(&self) -> (usize, usize) {
        self.data.dim()
    }

    pub fn insert_column(mut self, data: Matrix<f64>, name: &str) -> Result<DataFrame> {
        let name = ColumnType::from(name.to_string());
        let data = data.mapv(InnerType::from);
        let columns_idx = {
            self.columns.len()
        };
        self.columns.insert(name, columns_idx);
        self.data = match stack(Axis(1), &[self.data.view(), data.view()]) {
            Ok(z) => z,
            Err(_) => return Err(ErrorKind::StackFail.into()),
        };
        Ok(self)

    }

    pub fn drop_column(&mut self, names: &[&str]) -> Result<DataFrame> {
        let mut idxs = vec![];
        let names: Vec<ColumnType> =
            names.iter().map(|x| ColumnType::from(x.to_string())).collect();

        let new_map: &mut BTreeMap<ColumnType, usize> = &mut self.columns.clone();
        for name in names.iter() {
            let idx = new_map.remove(name);
            idxs.push(idx.unwrap());
            for (_, y) in new_map.iter_mut() {
                if y > &mut idx.unwrap() {
                    *y -= 1;
                }
            }
        }
        let cols = self.shape().1;
        let to_keep: Vec<usize> = (0..cols).filter(|x| !idxs.iter().any(|&y| y == *x)).collect();

        Ok(DataFrame {
            data: self.data.select(Axis(1), &to_keep[..]),
            columns: new_map.to_owned(),
            index: self.index.to_owned(),
        })
    }

    pub fn drop_row(&mut self, indexes: &[&str]) -> Result<DataFrame> {
        let mut idxs = vec![];
        let indexes: Vec<IndexType> =
            indexes.iter().map(|x| IndexType::from(x.to_string())).collect();

        let new_map: &mut BTreeMap<IndexType, usize> = &mut self.index.clone();
        for name in indexes.iter() {
            let idx = new_map.remove(name);
            idxs.push(idx.unwrap());
            for (_, y) in new_map.iter_mut() {
                if y > &mut idx.unwrap() {
                    *y -= 1;
                }
            }
        }
        let rows = self.shape().0;
        let to_keep: Vec<usize> = (0..rows).filter(|x| !idxs.iter().any(|&y| y == *x)).collect();
        Ok(DataFrame {
            data: self.data.select(Axis(0), &to_keep[..]),
            columns: self.columns.to_owned(),
            index: new_map.to_owned(),
        })
    }

    pub fn concat(&self, axis: Axis, other: &DataFrame) -> Result<DataFrame> {

        match axis {
            Axis(0) => {
                if self.shape().1 == other.shape().1 {
                    let new_map: BTreeMap<ColumnType, usize> = self.columns
                        .iter()
                        .map(|(x, y)| (x.to_owned(), *y))
                        .collect();

                    let new_index: BTreeMap<IndexType, usize> = concat_index_maps(&self.index,
                                                                                &other.index);

                    let new_matrix = match stack(Axis(0), &[self.data.view(), other.data.view()]) {
                        Ok(z) => z,
                        Err(_) => return Err(ErrorKind::StackFail.into()),
                    };
                    Ok(DataFrame {
                        data: new_matrix,
                        columns: new_map,
                        index: new_index,
                    })
                } else {
                    return Err(ErrorKind::ColumnShapeMismatch.into());
                }
            }
            Axis(1) => {
                if self.shape().0 == other.shape().0 {
                    let other_map: BTreeMap<ColumnType, usize> = other.columns
                        .iter()
                        .map(|(x, y)| (x.to_owned(), y + self.columns.len()))
                        .collect();
                    let new_map: BTreeMap<ColumnType, usize> = self.columns
                        .iter()
                        .chain(other_map.iter())
                        .map(|(x, y)| (x.to_owned(), *y))
                        .collect();

                    let new_matrix = match stack(Axis(1), &[self.data.view(), other.data.view()]) {
                        Ok(z) => z,
                        Err(_) => return Err(ErrorKind::StackFail.into()),
                    };
                    Ok(DataFrame {
                        data: new_matrix,
                        columns: new_map,
                        index: self.index.to_owned(),
                    })
                } else {
                    return Err(ErrorKind::RowShapeMismatch.into());
                }
            }
            _ => return Err(ErrorKind::InvalidAxis.into()),
        }

    }
    pub fn inner_join(&self, other: &DataFrame) -> Result<DataFrame> {

        let idxs: Vec<(IndexType, usize, Option<usize>)> =
            Join::new(JoinType::InnerJoin,
                      self.index.clone().into_iter(),
                      other.index.clone())
                .collect();

        if idxs.len() == 0 {
            return Err(ErrorKind::NoCommonValues.into());
        }

        let new_matrix: Matrix<InnerType> = {
            let i1: Vec<usize> = idxs.iter().map(|&(_, x, _)| x).collect();
            let i2: Vec<usize> = idxs.iter().map(|&(_, _, y)| y.unwrap()).collect();
            let mat1 = self.data.select(Axis(0), &i1[..]);
            let mat2 = other.data.select(Axis(0), &i2[..]);
            match stack(Axis(1), &[mat1.view(), mat2.view()]) {
                Ok(z) => z,
                Err(_) => return Err(ErrorKind::StackFail.into()),
            }
        };

        Ok(DataFrame {
            data: new_matrix,
            columns: concat_column_maps(&self.columns, &other.columns),
            index: merge_maps(&self.index, &other.index),
        })
    }
}

// To implement....?
// // parallelized join
// // parallelized concatenation
// // parallelized frequency counts
// // index dataframe?
// // sample rows
// // find/select
// // sort
// // statistics (mean, median, stdev)
// // print
//
// // statistics (mean, median, stdev)
// // print
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
pub use self::imp::*;

#[cfg(feature = "valgrind")]
#[path = "valgrind.rs"]
mod imp;

#[cfg(not(feature = "valgrind"))]
mod imp {
  use stack;
  #[derive(Debug)]
  pub struct StackId;
  /// No-op since no valgrind
  impl StackId {
    pub unsafe fn register<Stack: stack::Stack>(_stack: &mut Stack) -> StackId {
      StackId
    }
  }
}
<commit_msg>Remove unnecessary unsafety<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
pub use self::imp::*;

#[cfg(feature = "valgrind")]
#[path = "valgrind.rs"]
mod imp;

#[cfg(not(feature = "valgrind"))]
mod imp {
  use stack;
  #[derive(Debug)]
  pub struct StackId;
  /// No-op since no valgrind
  impl StackId {
    pub fn register<Stack: stack::Stack>(_stack: &mut Stack) -> StackId {
      StackId
    }
  }
}
<|endoftext|>


<commit_before>// (C)opyleft 2013 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_id = "geoip#0.1"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_uppercase_statics,
        unnecessary_qualification,
        managed_heap_memory)]

extern crate libc;

use libc::{c_void, c_char, c_int, c_ulong, c_float};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type GeoIP_ = *c_void;
type In6Addr = [u8, ..16];

struct GeoIPLookup_ {
    netmask: c_int
}

impl GeoIPLookup_ {
    fn new() -> GeoIPLookup_ {
        GeoIPLookup_ {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *c_char, flags: c_int) -> GeoIP_;
    fn GeoIP_delete(db: GeoIP_);
    fn GeoIP_name_by_ipnum_gl(db: GeoIP_, ipnum: c_ulong, gl: &GeoIPLookup_) -> *c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: GeoIP_, ipnum: In6Addr, gl: &GeoIPLookup_) -> *c_char;
    fn GeoIP_record_by_ipnum(db: GeoIP_, ipnum: c_ulong) -> *GeoIPRecord_;
    fn GeoIP_record_by_ipnum_v6(db: GeoIP_, ipnum: In6Addr) -> *GeoIPRecord_;
    fn GeoIPRecord_delete(gir: *GeoIPRecord_);
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIP {
    db: GeoIP_
}

pub struct GeoIPRecord_ {
    country_code: *c_char,
    country_code3: *c_char,
    country_name: *c_char,
    region: *c_char,
    city: *c_char,
    postal_code: *c_char,
    latitude: c_float,
    longitude: c_float,
    dma_code: c_int,
    area_code: c_int,
    charset: c_int,
    continent_code: *c_char,
    netmask: c_int
}

pub struct ASInfo {
    pub asn: uint,
    pub name: String,
    pub netmask: uint
}

pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: uint,
    pub area_code: uint,
    pub charset: uint,
    pub continent_code: Option<String>,
    pub netmask: uint
}

impl CityInfo {
    fn from_geoiprecord(res: &GeoIPRecord_) -> CityInfo {
        let country_code = unsafe { if res.country_code.is_null() {
            None
        } else {
            CString::new(res.country_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_code3 = unsafe { if res.country_code3.is_null() {
            None
        } else {
            CString::new(res.country_code3, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_name = unsafe { if res.country_name.is_null() {
            None
        } else {
            CString::new(res.country_name, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let region = unsafe { if res.region.is_null() {
            None
        } else {
            CString::new(res.region, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let city = unsafe { if res.city.is_null() {
            None
        } else {
            CString::new(res.city, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let postal_code = unsafe { if res.postal_code.is_null() {
            None
        } else {
            CString::new(res.postal_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let continent_code = unsafe { if res.continent_code.is_null() {
            None
        } else {
            CString::new(res.continent_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        CityInfo {
            country_code: country_code,
            country_code3: country_code3,
            country_name: country_name,
            region: region,
            city: city,
            postal_code: postal_code,
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as uint,
            area_code: res.area_code as uint,
            charset: res.charset as uint,
            continent_code: continent_code,
            netmask: res.netmask as uint
        }
    }
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

impl GeoIP {
    pub fn open(path: &Path, options: Options) -> Result<GeoIP, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        match db.is_null() {
            true => Err(format!("Can't open {}", file)),
            false => Ok(GeoIP {
                db: db
            })
        }
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_record_by_ipnum(self.db, ipnum)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_record_by_ipnum_v6(self.db, in6_addr)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let city_info = CityInfo::from_geoiprecord(&unsafe { *cres });
        unsafe { GeoIPRecord_delete(cres) };
        unsafe { std::mem::forget(cres) };
        Some(city_info)
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIPLookup_::new();
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_name_by_ipnum_gl(self.db, ipnum, &gl)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_name_by_ipnum_v6_gl(self.db, in6_addr, &gl)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(' ', 1);
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as uint
        };
        Some(as_info)
    }
}

impl Drop for GeoIP {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoLiteCity.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap().as_slice() == "Mountain View");
}
<commit_msg>Use GeoIP_set_charset() to always use UTF8 Suggested by @oschwald<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_id = "geoip#0.1"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_uppercase_statics,
        unnecessary_qualification,
        managed_heap_memory)]

extern crate libc;

use libc::{c_void, c_char, c_int, c_ulong, c_float};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type GeoIP_ = *c_void;
type In6Addr = [u8, ..16];

struct GeoIPLookup_ {
    netmask: c_int
}

impl GeoIPLookup_ {
    fn new() -> GeoIPLookup_ {
        GeoIPLookup_ {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *c_char, flags: c_int) -> GeoIP_;
    fn GeoIP_delete(db: GeoIP_);
    fn GeoIP_name_by_ipnum_gl(db: GeoIP_, ipnum: c_ulong, gl: &GeoIPLookup_) -> *c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: GeoIP_, ipnum: In6Addr, gl: &GeoIPLookup_) -> *c_char;
    fn GeoIP_record_by_ipnum(db: GeoIP_, ipnum: c_ulong) -> *GeoIPRecord_;
    fn GeoIP_record_by_ipnum_v6(db: GeoIP_, ipnum: In6Addr) -> *GeoIPRecord_;
    fn GeoIPRecord_delete(gir: *GeoIPRecord_);
    fn GeoIP_set_charset(db: GeoIP_, charset: c_int) -> c_int;
}

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIP {
    db: GeoIP_
}

pub struct GeoIPRecord_ {
    country_code: *c_char,
    country_code3: *c_char,
    country_name: *c_char,
    region: *c_char,
    city: *c_char,
    postal_code: *c_char,
    latitude: c_float,
    longitude: c_float,
    dma_code: c_int,
    area_code: c_int,
    charset: c_int,
    continent_code: *c_char,
    netmask: c_int
}

pub struct ASInfo {
    pub asn: uint,
    pub name: String,
    pub netmask: uint
}

pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: uint,
    pub area_code: uint,
    pub charset: uint,
    pub continent_code: Option<String>,
    pub netmask: uint
}

impl CityInfo {
    fn from_geoiprecord(res: &GeoIPRecord_) -> CityInfo {
        let country_code = unsafe { if res.country_code.is_null() {
            None
        } else {
            CString::new(res.country_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_code3 = unsafe { if res.country_code3.is_null() {
            None
        } else {
            CString::new(res.country_code3, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let country_name = unsafe { if res.country_name.is_null() {
            None
        } else {
            CString::new(res.country_name, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let region = unsafe { if res.region.is_null() {
            None
        } else {
            CString::new(res.region, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let city = unsafe { if res.city.is_null() {
            None
        } else {
            CString::new(res.city, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let postal_code = unsafe { if res.postal_code.is_null() {
            None
        } else {
            CString::new(res.postal_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        let continent_code = unsafe { if res.continent_code.is_null() {
            None
        } else {
            CString::new(res.continent_code, false).as_str().
                and_then(|str| Some(String::from_str(str)))
        }};
        CityInfo {
            country_code: country_code,
            country_code3: country_code3,
            country_name: country_name,
            region: region,
            city: city,
            postal_code: postal_code,
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as uint,
            area_code: res.area_code as uint,
            charset: res.charset as uint,
            continent_code: continent_code,
            netmask: res.netmask as uint
        }
    }
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

impl GeoIP {
    pub fn open(path: &Path, options: Options) -> Result<GeoIP, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { GeoIP_set_charset(db, UTF8 as c_int) } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIP { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_record_by_ipnum(self.db, ipnum)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_record_by_ipnum_v6(self.db, in6_addr)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let city_info = CityInfo::from_geoiprecord(&unsafe { *cres });
        unsafe { GeoIPRecord_delete(cres) };
        unsafe { std::mem::forget(cres) };
        Some(city_info)
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIPLookup_::new();
        let cres = match ip {
            Ipv4Addr(a, b, c, d) => {
                let ipnum: c_ulong =
                    (a as c_ulong << 24) | (b as c_ulong << 16) |
                    (c as c_ulong << 8)  | (d as c_ulong);
                unsafe {
                    GeoIP_name_by_ipnum_gl(self.db, ipnum, &gl)
                }
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                let in6_addr: In6Addr = [(a >> 8) as u8, a as u8,
                                         (b >> 8) as u8, b as u8,
                                         (c >> 8) as u8, c as u8,
                                         (d >> 8) as u8, d as u8,
                                         (e >> 8) as u8, e as u8,
                                         (f >> 8) as u8, f as u8,
                                         (g >> 8) as u8, g as u8,
                                         (h >> 8) as u8, h as u8];
                unsafe {
                    GeoIP_name_by_ipnum_v6_gl(self.db, in6_addr, &gl)
                }
            }
        };
        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(' ', 1);
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as uint
        };
        Some(as_info)
    }
}

impl Drop for GeoIP {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIP::open(&from_str("/opt/geoip/GeoLiteCity.dat").unwrap(), MemoryCache) {
        Err(err) => fail!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap().as_slice() == "Mountain View");
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use mo::MultiObjective;
use std::f32;

#[derive(Debug)]
pub struct SolutionRankDist {
    pub rank: u32,
    pub dist: f32,
    pub idx: usize,
}

impl PartialEq for SolutionRankDist {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.rank == other.rank && self.dist == other.dist
    }
}

// Implement the crowding-distance comparison operator.
impl PartialOrd for SolutionRankDist {
    #[inline]
    // compare on rank first (ASC), then on dist (DESC)
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self.rank.partial_cmp(&other.rank) {
            Some(Ordering::Equal) => {
                // first criterion equal, second criterion decides
                // reverse ordering
                self.dist.partial_cmp(&other.dist).map(|i| i.reverse())
            }
            other => other,
        }
    }
}

pub fn crowding_distance_assignment<P: MultiObjective>(solutions: &[P],
                                                       common_rank: u32,
                                                       individuals_idx: &[usize],
                                                       num_objectives: usize)
                                                       -> Vec<SolutionRankDist> {
    assert!(num_objectives > 0);

    let l = individuals_idx.len();
    let mut distance: Vec<f32> = (0..l).map(|_| 0.0).collect();
    let mut indices: Vec<usize> = (0..l).map(|i| i).collect();

    for m in 0..num_objectives {
        // sort using objective `m`
        indices.sort_by(|&a, &b| {
            solutions[individuals_idx[a]].cmp_objective(&solutions[individuals_idx[b]], m)
        });
        distance[indices[0]] = f32::INFINITY;
        distance[indices[l - 1]] = f32::INFINITY;

        let min_idx = individuals_idx[indices[0]];
        let max_idx = individuals_idx[indices[l - 1]];

        let dist_max_min = solutions[max_idx].dist_objective(&solutions[min_idx], m);
        if dist_max_min != 0.0 {
            let norm = num_objectives as f32 * dist_max_min;
            debug_assert!(norm != 0.0);
            for i in 1..(l - 1) {
                let next_idx = individuals_idx[indices[i + 1]];
                let prev_idx = individuals_idx[indices[i - 1]];
                let dist = solutions[next_idx].dist_objective(&solutions[prev_idx], m);
                debug_assert!(dist >= 0.0);
                distance[indices[i]] += dist / norm;
            }
        }
    }

    return indices.iter()
                  .map(|&i| {
                      SolutionRankDist {
                          idx: individuals_idx[i],
                          rank: common_rank,
                          dist: distance[i],
                      }
                  })
                  .collect();
}
<commit_msg>Simplify the code by removing one extra indirection. work directly on SolutionRankDist.<commit_after>use std::cmp::Ordering;
use mo::MultiObjective;
use std::f32;

#[derive(Debug)]
pub struct SolutionRankDist {
    pub rank: u32,
    pub dist: f32,
    pub idx: usize,
}

impl PartialEq for SolutionRankDist {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.rank == other.rank && self.dist == other.dist
    }
}

// Implement the crowding-distance comparison operator.
impl PartialOrd for SolutionRankDist {
    #[inline]
    // compare on rank first (ASC), then on dist (DESC)
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self.rank.partial_cmp(&other.rank) {
            Some(Ordering::Equal) => {
                // first criterion equal, second criterion decides
                // reverse ordering
                self.dist.partial_cmp(&other.dist).map(|i| i.reverse())
            }
            other => other,
        }
    }
}

pub fn crowding_distance_assignment<P: MultiObjective>(solutions: &[P],
                                                       common_rank: u32,
                                                       individuals_idx: &[usize],
                                                       num_objectives: usize)
                                                       -> Vec<SolutionRankDist> {
    assert!(num_objectives > 0);

    let mut s: Vec<_> = individuals_idx.iter()
                                       .map(|&i| {
                                           SolutionRankDist {
                                               rank: common_rank,
                                               dist: 0.0,
                                               idx: i,
                                           }
                                       })
                                       .collect();
    let l = s.len();

    for m in 0..num_objectives {
        // sort using objective `m`
        s.sort_by(|a, b| solutions[a.idx].cmp_objective(&solutions[b.idx], m));

        // assign infinite crowding distance to edges.
        s[0].dist = f32::INFINITY;
        s[l - 1].dist = f32::INFINITY;

        let min_idx = s[0].idx;
        let max_idx = s[l - 1].idx;

        let dist_max_min = solutions[max_idx].dist_objective(&solutions[min_idx], m);
        if dist_max_min != 0.0 {
            let norm = num_objectives as f32 * dist_max_min;
            debug_assert!(norm != 0.0);
            for i in 1..(l - 1) {
                let next_idx = s[i + 1].idx;
                let prev_idx = s[i - 1].idx;
                let dist = solutions[next_idx].dist_objective(&solutions[prev_idx], m);
                debug_assert!(dist >= 0.0);
                s[i].dist += dist / norm;
            }
        }
    }

    return s;
}
<|endoftext|>


<commit_before>// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.

use configuration::{ConfigChange, ConfigManager, Configuration};
use std::sync::Arc;
use tikv_util::config::VersionTrack;

const DEFAULT_DETECT_TIMES: u64 = 10;
const DEFAULT_SAMPLE_THRESHOLD: u64 = 100;
pub(crate) const DEFAULT_SAMPLE_NUM: usize = 20;
const DEFAULT_QPS_THRESHOLD: usize = 3000;
const DEFAULT_BYTE_THRESHOLD: usize = 30 * 1024 * 1024;

// We get balance score by abs(sample.left-sample.right)/(sample.right+sample.left). It will be used to measure left and right balance
const DEFAULT_SPLIT_BALANCE_SCORE: f64 = 0.25;
// We get contained score by sample.contained/(sample.right+sample.left+sample.contained). It will be used to avoid to split regions requested by range.
const DEFAULT_SPLIT_CONTAINED_SCORE: f64 = 0.5;

#[serde(default)]
#[serde(rename_all = "kebab-case")]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Configuration)]
pub struct SplitConfig {
    pub qps_threshold: usize,
    pub split_balance_score: f64,
    pub split_contained_score: f64,
    pub detect_times: u64,
    pub sample_num: usize,
    pub sample_threshold: u64,
    pub byte_threshold: usize,
}

impl Default for SplitConfig {
    fn default() -> SplitConfig {
        SplitConfig {
            qps_threshold: DEFAULT_QPS_THRESHOLD,
            split_balance_score: DEFAULT_SPLIT_BALANCE_SCORE,
            split_contained_score: DEFAULT_SPLIT_CONTAINED_SCORE,
            detect_times: DEFAULT_DETECT_TIMES,
            sample_num: DEFAULT_SAMPLE_NUM,
            sample_threshold: DEFAULT_SAMPLE_THRESHOLD,
            byte_threshold: DEFAULT_BYTE_THRESHOLD,
        }
    }
}

impl SplitConfig {
    pub fn validate(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
        if self.split_balance_score > 1.0
            || self.split_balance_score < 0.0
            || self.split_contained_score > 1.0
            || self.split_contained_score < 0.0
        {
            return Err(
                ("split_balance_score or split_contained_score should be between 0 and 1.").into(),
            );
        }
        if self.sample_num >= self.qps_threshold {
            return Err(
                ("sample_num should be less than qps_threshold for load-base-split.").into(),
            );
        }
        Ok(())
    }
}

#[derive(Clone, Default)]
pub struct SplitConfigManager(pub Arc<VersionTrack<SplitConfig>>);

impl ConfigManager for SplitConfigManager {
    fn dispatch(
        &mut self,
        change: ConfigChange,
    ) -> std::result::Result<(), Box<dyn std::error::Error>> {
        {
            let change = change.clone();
            self.0
                .update(move |cfg: &mut SplitConfig| cfg.update(change));
        }
        info!(
            "load base split config changed";
            "change" => ?change,
        );
        Ok(())
    }
}

impl std::ops::Deref for SplitConfigManager {
    type Target = Arc<VersionTrack<SplitConfig>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
<commit_msg>fix backward compatibility in load base split config (#9820)<commit_after>// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.

use configuration::{ConfigChange, ConfigManager, Configuration};
use std::sync::Arc;
use tikv_util::config::VersionTrack;

const DEFAULT_DETECT_TIMES: u64 = 10;
const DEFAULT_SAMPLE_THRESHOLD: u64 = 100;
pub(crate) const DEFAULT_SAMPLE_NUM: usize = 20;
const DEFAULT_QPS_THRESHOLD: usize = 3000;
const DEFAULT_BYTE_THRESHOLD: usize = 30 * 1024 * 1024;

// We get balance score by abs(sample.left-sample.right)/(sample.right+sample.left). It will be used to measure left and right balance
const DEFAULT_SPLIT_BALANCE_SCORE: f64 = 0.25;
// We get contained score by sample.contained/(sample.right+sample.left+sample.contained). It will be used to avoid to split regions requested by range.
const DEFAULT_SPLIT_CONTAINED_SCORE: f64 = 0.5;

#[serde(default)]
#[serde(rename_all = "kebab-case")]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Configuration)]
pub struct SplitConfig {
    pub qps_threshold: usize,
    pub split_balance_score: f64,
    pub split_contained_score: f64,
    pub detect_times: u64,
    pub sample_num: usize,
    pub sample_threshold: u64,
    pub byte_threshold: usize,
    // deprecated.
    #[config(skip)]
    #[doc(hidden)]
    #[serde(skip_serializing)]
    pub size_threshold: Option<usize>,
    // deprecated.
    #[config(skip)]
    #[doc(hidden)]
    #[serde(skip_serializing)]
    pub key_threshold: Option<usize>,
}

impl Default for SplitConfig {
    fn default() -> SplitConfig {
        SplitConfig {
            qps_threshold: DEFAULT_QPS_THRESHOLD,
            split_balance_score: DEFAULT_SPLIT_BALANCE_SCORE,
            split_contained_score: DEFAULT_SPLIT_CONTAINED_SCORE,
            detect_times: DEFAULT_DETECT_TIMES,
            sample_num: DEFAULT_SAMPLE_NUM,
            sample_threshold: DEFAULT_SAMPLE_THRESHOLD,
            byte_threshold: DEFAULT_BYTE_THRESHOLD,
            size_threshold: None, // deprecated.
            key_threshold: None,  // deprecated.
        }
    }
}

impl SplitConfig {
    pub fn validate(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
        if self.split_balance_score > 1.0
            || self.split_balance_score < 0.0
            || self.split_contained_score > 1.0
            || self.split_contained_score < 0.0
        {
            return Err(
                ("split_balance_score or split_contained_score should be between 0 and 1.").into(),
            );
        }
        if self.sample_num >= self.qps_threshold {
            return Err(
                ("sample_num should be less than qps_threshold for load-base-split.").into(),
            );
        }
        Ok(())
    }
}

#[derive(Clone, Default)]
pub struct SplitConfigManager(pub Arc<VersionTrack<SplitConfig>>);

impl ConfigManager for SplitConfigManager {
    fn dispatch(
        &mut self,
        change: ConfigChange,
    ) -> std::result::Result<(), Box<dyn std::error::Error>> {
        {
            let change = change.clone();
            self.0
                .update(move |cfg: &mut SplitConfig| cfg.update(change));
        }
        info!(
            "load base split config changed";
            "change" => ?change,
        );
        Ok(())
    }
}

impl std::ops::Deref for SplitConfigManager {
    type Target = Arc<VersionTrack<SplitConfig>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
<|endoftext|>


<commit_before>use binary::{
    async_trait::async_trait,
    eyre::{bail, Result},
    Binary, BinaryTrait,
};

pub struct NodeBinary {}

#[async_trait]
impl BinaryTrait for NodeBinary {
    fn spec(&self) -> Binary {
        Binary::new(
            "node",
            &[],
            // Release list at https://nodejs.org/en/download/releases/
            &[
                "16.4.0", "16.4.1", "16.4.2", "16.5.0", "16.6.0", "16.6.1", "16.6.2", "16.7.0",
                "16.8.0", "16.9.0", "16.9.1", "16.10.0", "16.11.0", "16.11.1", "16.12.0",
                "16.13.0", "17.0.0", "17.0.1",
            ],
        )
    }

    async fn install_version(&self, version: &str, os: &str, arch: &str) -> Result<()> {
        let url = format!(
            "https://nodejs.org/dist/v{version}/node-v{version}-",
            version = version
        ) + match os {
            "macos" => match arch {
                "arm" => "darwin-arm64.tar.gz",
                _ => "darwin-x64.tar.gz",
            },
            "windows" => match arch {
                "x86" => "win-x86.zip",
                _ => "win-x64.zip",
            },
            "linux" => match arch {
                "arm" => "linux-arm64.tar.xz",
                _ => "linux-x64.tar.xz",
            },
            _ => bail!("Unable to determine Node download URL"),
        };

        let archive = self.download(&url).await?;
        let dest = self.dir(Some(version.into()), true)?;
        self.extract(&archive, 1, &dest)?;
        self.executable(&dest, &["bin/node", "bin/npm", "node.exe", "npm"])?;

        Ok(())
    }
}
<commit_msg>chore(Node binary): Update installable versions<commit_after>use binary::{
    async_trait::async_trait,
    eyre::{bail, Result},
    Binary, BinaryTrait,
};

pub struct NodeBinary {}

#[async_trait]
impl BinaryTrait for NodeBinary {
    #[rustfmt::skip]
    fn spec(&self) -> Binary {
        Binary::new(
            "node",
            &[],
            // Release list at https://nodejs.org/en/download/releases/
            // Current strategy is to support the latest patch version of each minor version.
            // Support for older minor versions may be progressively  dropped if there are no
            // plugins relying on them.
            &[
                "16.10.0",
                "16.11.1",
                "16.12.0",
                "16.13.1",
                "17.0.1",
                "17.1.0",
                "17.2.0"
            ],
        )
    }

    async fn install_version(&self, version: &str, os: &str, arch: &str) -> Result<()> {
        let url = format!(
            "https://nodejs.org/dist/v{version}/node-v{version}-",
            version = version
        ) + match os {
            "macos" => match arch {
                "arm" => "darwin-arm64.tar.gz",
                _ => "darwin-x64.tar.gz",
            },
            "windows" => match arch {
                "x86" => "win-x86.zip",
                _ => "win-x64.zip",
            },
            "linux" => match arch {
                "arm" => "linux-arm64.tar.xz",
                _ => "linux-x64.tar.xz",
            },
            _ => bail!("Unable to determine Node download URL"),
        };

        let archive = self.download(&url).await?;
        let dest = self.dir(Some(version.into()), true)?;
        self.extract(&archive, 1, &dest)?;
        self.executable(&dest, &["bin/node", "bin/npm", "node.exe", "npm"])?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use utils::bigint::M256;
use utils::opcode::Opcode;
use std::cmp::min;
use super::errors::PCError;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Instruction {
    STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, MULMOD, EXP,
    SIGNEXTEND, LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE,
    SHA3, ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD,
    CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE,
    EXTCODESIZE, EXTCODECOPY, BLOCKHASH, COINBASE, TIMESTAMP, NUMBER,
    DIFFICULTY, GASLIMIT, POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE,
    JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, CREATE, CALL, CALLCODE,
    RETURN, DELEGATECALL, SUICIDE,

    PUSH(M256),
    DUP(usize),
    SWAP(usize),
    LOG(usize),
}

pub struct PC {
    position: usize,
    code: Vec<u8>,
    valids: Vec<bool>,
}

impl Default for PC {
    fn default() -> PC {
        PC {
            position: 0,
            code: Vec::new(),
            valids: Vec::new(),
        }
    }
}

impl PC {
    pub fn new(code: &[u8]) -> Self {
        let code: Vec<u8> = code.into();
        let mut valids: Vec<bool> = Vec::with_capacity(code.len());
        valids.resize(code.len(), false);

        let mut i = 0;
        while i < code.len() {
            let opcode: Opcode = code[i].into();
            match opcode {
                Opcode::JUMPDEST => {
                    valids[i] = true;
                    i = i + 1;
                },
                Opcode::PUSH(v) => {
                    i = i + v + 1;
                },
                _ => {
                    i = i + 1;
                }
            }
        }

        PC {
            position: 0,
            code: code,
            valids: valids,
        }
    }

    fn read_bytes(&self, from_position: usize, byte_count: usize) -> Result<M256, PCError> {
        if from_position > self.code.len() {
            return Err(PCError::Overflow);
        }
        let position = from_position;
        if position.checked_add(byte_count).is_none() {
            return Err(PCError::IndexNotSupported);
        }
        let max = min(position + byte_count, self.code.len());
        Ok(M256::from(&self.code[position..max]))
    }

    pub fn jump(&mut self, position: usize) -> Result<(), PCError> {
        if position >= self.code.len() {
            return Err(PCError::Overflow);
        }

        if !self.valids[position] {
            return Err(PCError::BadJumpDest);
        }

        self.position = position;
        Ok(())
    }

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

    pub fn check_valid(&self, position: usize) -> Result<(), PCError> {
        if self.is_valid(position) {
            Ok(())
        } else {
            Err(PCError::BadJumpDest)
        }
    }

    pub fn is_valid(&self, position: usize) -> bool {
        if position >= self.code.len() {
            return false;
        }

        if !self.valids[position] {
            return false;
        }

        return true;
    }

    pub fn is_end(&self) -> bool {
        self.position == self.code.len()
    }

    pub fn peek(&self) -> Result<Instruction, PCError> {
        let position = self.position;
        if position >= self.code.len() {
            return Err(PCError::Overflow);
        }
        let opcode: Opcode = self.code[position].into();
        Ok(match opcode {
            Opcode::STOP => Instruction::STOP,
            Opcode::ADD => Instruction::ADD,
            Opcode::MUL => Instruction::MUL,
            Opcode::SUB => Instruction::SUB,
            Opcode::DIV => Instruction::DIV,
            Opcode::SDIV => Instruction::SDIV,
            Opcode::MOD => Instruction::MOD,
            Opcode::SMOD => Instruction::SMOD,
            Opcode::ADDMOD => Instruction::ADDMOD,
            Opcode::MULMOD => Instruction::MULMOD,
            Opcode::EXP => Instruction::EXP,
            Opcode::SIGNEXTEND => Instruction::SIGNEXTEND,

            Opcode::LT => Instruction::LT,
            Opcode::GT => Instruction::GT,
            Opcode::SLT => Instruction::SLT,
            Opcode::SGT => Instruction::SGT,
            Opcode::EQ => Instruction::EQ,
            Opcode::ISZERO => Instruction::ISZERO,
            Opcode::AND => Instruction::AND,
            Opcode::OR => Instruction::OR,
            Opcode::XOR => Instruction::XOR,
            Opcode::NOT => Instruction::NOT,
            Opcode::BYTE => Instruction::BYTE,

            Opcode::SHA3 => Instruction::SHA3,

            Opcode::ADDRESS => Instruction::ADDRESS,
            Opcode::BALANCE => Instruction::BALANCE,
            Opcode::ORIGIN => Instruction::ORIGIN,
            Opcode::CALLER => Instruction::CALLER,
            Opcode::CALLVALUE => Instruction::CALLVALUE,
            Opcode::CALLDATALOAD => Instruction::CALLDATALOAD,
            Opcode::CALLDATASIZE => Instruction::CALLDATASIZE,
            Opcode::CALLDATACOPY => Instruction::CALLDATACOPY,
            Opcode::CODESIZE => Instruction::CODESIZE,
            Opcode::CODECOPY => Instruction::CODECOPY,
            Opcode::GASPRICE => Instruction::GASPRICE,
            Opcode::EXTCODESIZE => Instruction::EXTCODESIZE,
            Opcode::EXTCODECOPY => Instruction::EXTCODECOPY,

            Opcode::BLOCKHASH => Instruction::BLOCKHASH,
            Opcode::COINBASE => Instruction::COINBASE,
            Opcode::TIMESTAMP => Instruction::TIMESTAMP,
            Opcode::NUMBER => Instruction::NUMBER,
            Opcode::DIFFICULTY => Instruction::DIFFICULTY,
            Opcode::GASLIMIT => Instruction::GASLIMIT,

            Opcode::POP => Instruction::POP,
            Opcode::MLOAD => Instruction::MLOAD,
            Opcode::MSTORE => Instruction::MSTORE,
            Opcode::MSTORE8 => Instruction::MSTORE8,
            Opcode::SLOAD => Instruction::SLOAD,
            Opcode::SSTORE => Instruction::SSTORE,
            Opcode::JUMP => Instruction::JUMP,
            Opcode::JUMPI => Instruction::JUMPI,
            Opcode::PC => Instruction::PC,
            Opcode::MSIZE => Instruction::MSIZE,
            Opcode::GAS => Instruction::GAS,
            Opcode::JUMPDEST => Instruction::JUMPDEST,

            Opcode::PUSH(v) => {
                let param = self.read_bytes(position + 1, v)?;
                Instruction::PUSH(param)
            },

            Opcode::DUP(v) => Instruction::DUP(v),
            Opcode::SWAP(v) => Instruction::SWAP(v),
            Opcode::LOG(v) => Instruction::LOG(v),

            Opcode::CREATE => Instruction::CREATE,
            Opcode::CALL => Instruction::CALL,
            Opcode::CALLCODE => Instruction::CALLCODE,
            Opcode::RETURN => Instruction::RETURN,
            Opcode::DELEGATECALL => Instruction::DELEGATECALL,

            Opcode::INVALID => {
                return Err(PCError::InvalidOpcode);
            },
            Opcode::SUICIDE => Instruction::SUICIDE,
        })
    }

    pub fn read(&mut self) -> Result<Instruction, PCError> {
        let result = self.peek()?;
        let opcode: Opcode = self.code[self.position].into();
        match opcode {
            Opcode::PUSH(v) => {
                self.position = self.position + v + 1;
            },
            _ => {
                self.position = self.position + 1;
            },
        }
        Ok(result)
    }
}
<commit_msg>Problem: PUSH read might cause pc overflow Solution: use min<commit_after>use utils::bigint::M256;
use utils::opcode::Opcode;
use std::cmp::min;
use super::errors::PCError;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Instruction {
    STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, MULMOD, EXP,
    SIGNEXTEND, LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE,
    SHA3, ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD,
    CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE,
    EXTCODESIZE, EXTCODECOPY, BLOCKHASH, COINBASE, TIMESTAMP, NUMBER,
    DIFFICULTY, GASLIMIT, POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE,
    JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, CREATE, CALL, CALLCODE,
    RETURN, DELEGATECALL, SUICIDE,

    PUSH(M256),
    DUP(usize),
    SWAP(usize),
    LOG(usize),
}

pub struct PC {
    position: usize,
    code: Vec<u8>,
    valids: Vec<bool>,
}

impl Default for PC {
    fn default() -> PC {
        PC {
            position: 0,
            code: Vec::new(),
            valids: Vec::new(),
        }
    }
}

impl PC {
    pub fn new(code: &[u8]) -> Self {
        let code: Vec<u8> = code.into();
        let mut valids: Vec<bool> = Vec::with_capacity(code.len());
        valids.resize(code.len(), false);

        let mut i = 0;
        while i < code.len() {
            let opcode: Opcode = code[i].into();
            match opcode {
                Opcode::JUMPDEST => {
                    valids[i] = true;
                    i = i + 1;
                },
                Opcode::PUSH(v) => {
                    i = i + v + 1;
                },
                _ => {
                    i = i + 1;
                }
            }
        }

        PC {
            position: 0,
            code: code,
            valids: valids,
        }
    }

    fn read_bytes(&self, from_position: usize, byte_count: usize) -> Result<M256, PCError> {
        if from_position > self.code.len() {
            return Err(PCError::Overflow);
        }
        let position = from_position;
        if position.checked_add(byte_count).is_none() {
            return Err(PCError::IndexNotSupported);
        }
        let max = min(position + byte_count, self.code.len());
        Ok(M256::from(&self.code[position..max]))
    }

    pub fn jump(&mut self, position: usize) -> Result<(), PCError> {
        if position >= self.code.len() {
            return Err(PCError::Overflow);
        }

        if !self.valids[position] {
            return Err(PCError::BadJumpDest);
        }

        self.position = position;
        Ok(())
    }

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

    pub fn check_valid(&self, position: usize) -> Result<(), PCError> {
        if self.is_valid(position) {
            Ok(())
        } else {
            Err(PCError::BadJumpDest)
        }
    }

    pub fn is_valid(&self, position: usize) -> bool {
        if position >= self.code.len() {
            return false;
        }

        if !self.valids[position] {
            return false;
        }

        return true;
    }

    pub fn is_end(&self) -> bool {
        self.position == self.code.len()
    }

    pub fn peek(&self) -> Result<Instruction, PCError> {
        let position = self.position;
        if position >= self.code.len() {
            return Err(PCError::Overflow);
        }
        let opcode: Opcode = self.code[position].into();
        Ok(match opcode {
            Opcode::STOP => Instruction::STOP,
            Opcode::ADD => Instruction::ADD,
            Opcode::MUL => Instruction::MUL,
            Opcode::SUB => Instruction::SUB,
            Opcode::DIV => Instruction::DIV,
            Opcode::SDIV => Instruction::SDIV,
            Opcode::MOD => Instruction::MOD,
            Opcode::SMOD => Instruction::SMOD,
            Opcode::ADDMOD => Instruction::ADDMOD,
            Opcode::MULMOD => Instruction::MULMOD,
            Opcode::EXP => Instruction::EXP,
            Opcode::SIGNEXTEND => Instruction::SIGNEXTEND,

            Opcode::LT => Instruction::LT,
            Opcode::GT => Instruction::GT,
            Opcode::SLT => Instruction::SLT,
            Opcode::SGT => Instruction::SGT,
            Opcode::EQ => Instruction::EQ,
            Opcode::ISZERO => Instruction::ISZERO,
            Opcode::AND => Instruction::AND,
            Opcode::OR => Instruction::OR,
            Opcode::XOR => Instruction::XOR,
            Opcode::NOT => Instruction::NOT,
            Opcode::BYTE => Instruction::BYTE,

            Opcode::SHA3 => Instruction::SHA3,

            Opcode::ADDRESS => Instruction::ADDRESS,
            Opcode::BALANCE => Instruction::BALANCE,
            Opcode::ORIGIN => Instruction::ORIGIN,
            Opcode::CALLER => Instruction::CALLER,
            Opcode::CALLVALUE => Instruction::CALLVALUE,
            Opcode::CALLDATALOAD => Instruction::CALLDATALOAD,
            Opcode::CALLDATASIZE => Instruction::CALLDATASIZE,
            Opcode::CALLDATACOPY => Instruction::CALLDATACOPY,
            Opcode::CODESIZE => Instruction::CODESIZE,
            Opcode::CODECOPY => Instruction::CODECOPY,
            Opcode::GASPRICE => Instruction::GASPRICE,
            Opcode::EXTCODESIZE => Instruction::EXTCODESIZE,
            Opcode::EXTCODECOPY => Instruction::EXTCODECOPY,

            Opcode::BLOCKHASH => Instruction::BLOCKHASH,
            Opcode::COINBASE => Instruction::COINBASE,
            Opcode::TIMESTAMP => Instruction::TIMESTAMP,
            Opcode::NUMBER => Instruction::NUMBER,
            Opcode::DIFFICULTY => Instruction::DIFFICULTY,
            Opcode::GASLIMIT => Instruction::GASLIMIT,

            Opcode::POP => Instruction::POP,
            Opcode::MLOAD => Instruction::MLOAD,
            Opcode::MSTORE => Instruction::MSTORE,
            Opcode::MSTORE8 => Instruction::MSTORE8,
            Opcode::SLOAD => Instruction::SLOAD,
            Opcode::SSTORE => Instruction::SSTORE,
            Opcode::JUMP => Instruction::JUMP,
            Opcode::JUMPI => Instruction::JUMPI,
            Opcode::PC => Instruction::PC,
            Opcode::MSIZE => Instruction::MSIZE,
            Opcode::GAS => Instruction::GAS,
            Opcode::JUMPDEST => Instruction::JUMPDEST,

            Opcode::PUSH(v) => {
                let param = self.read_bytes(position + 1, v)?;
                Instruction::PUSH(param)
            },

            Opcode::DUP(v) => Instruction::DUP(v),
            Opcode::SWAP(v) => Instruction::SWAP(v),
            Opcode::LOG(v) => Instruction::LOG(v),

            Opcode::CREATE => Instruction::CREATE,
            Opcode::CALL => Instruction::CALL,
            Opcode::CALLCODE => Instruction::CALLCODE,
            Opcode::RETURN => Instruction::RETURN,
            Opcode::DELEGATECALL => Instruction::DELEGATECALL,

            Opcode::INVALID => {
                return Err(PCError::InvalidOpcode);
            },
            Opcode::SUICIDE => Instruction::SUICIDE,
        })
    }

    pub fn read(&mut self) -> Result<Instruction, PCError> {
        let result = self.peek()?;
        let opcode: Opcode = self.code[self.position].into();
        match opcode {
            Opcode::PUSH(v) => {
                self.position = min(self.position + v + 1, self.code.len());
            },
            _ => {
                self.position = self.position + 1;
            },
        }
        Ok(result)
    }
}
<|endoftext|>


<commit_before>use eew::*;

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Copy)]
pub enum EEWPhase {
	Cancel,
	FastForecast,
	Forecast,
	Alert
}

impl EEW {

	pub fn get_eew_phase(&self) -> Option<EEWPhase>
	{
		match self.kind {

			Kind::Cancel | Kind::DrillCancel => Some(EEWPhase::Cancel),

			Kind::Normal | Kind::Drill | Kind::Reference | Kind::Test => {

				match self.detail.as_ref().map(|d| d.warning_status) {
					Some(WarningStatus::Alert) => Some(EEWPhase::Alert),
					Some(WarningStatus::Forecast) => {
						match self.issue_pattern {
							IssuePattern::IntensityOnly => Some(EEWPhase::FastForecast),
							IssuePattern::LowAccuracy | IssuePattern::HighAccuracy => Some(EEWPhase::Forecast),
							_ => None,
						}
					}
					_ => None,
				}
			}
		}
	}

	pub fn is_high_accuracy(&self) -> bool
	{
		self.issue_pattern == IssuePattern::HighAccuracy
	}

	pub fn is_last(&self) -> bool
	{
		match self.status {
			Status::LastWithCorrection | Status::Last => true,
			_ => false
		}
	}

	pub fn is_drill(&self) -> bool
	{
		self.kind == Kind::Drill || self.kind == Kind::DrillCancel
	}
}
<commit_msg>EEW: Add is_test method<commit_after>use eew::*;

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Copy)]
pub enum EEWPhase {
	Cancel,
	FastForecast,
	Forecast,
	Alert
}

impl EEW {

	pub fn get_eew_phase(&self) -> Option<EEWPhase>
	{
		match self.kind {

			Kind::Cancel | Kind::DrillCancel => Some(EEWPhase::Cancel),

			Kind::Normal | Kind::Drill | Kind::Reference | Kind::Test => {

				match self.detail.as_ref().map(|d| d.warning_status) {
					Some(WarningStatus::Alert) => Some(EEWPhase::Alert),
					Some(WarningStatus::Forecast) => {
						match self.issue_pattern {
							IssuePattern::IntensityOnly => Some(EEWPhase::FastForecast),
							IssuePattern::LowAccuracy | IssuePattern::HighAccuracy => Some(EEWPhase::Forecast),
							_ => None,
						}
					}
					_ => None,
				}
			}
		}
	}

	pub fn is_high_accuracy(&self) -> bool
	{
		self.issue_pattern == IssuePattern::HighAccuracy
	}

	pub fn is_last(&self) -> bool
	{
		match self.status {
			Status::LastWithCorrection | Status::Last => true,
			_ => false
		}
	}

	pub fn is_drill(&self) -> bool
	{
		self.kind == Kind::Drill || self.kind == Kind::DrillCancel
	}

	pub fn is_test(&self) -> bool
	{
		self.kind == Kind::Reference || self.kind == Kind::Test
	}
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![allow(float_cmp)]

extern crate cql_bindgen;
extern crate num;

use std::mem;
use std::ffi::CString;

use cql_bindgen::*;

#[derive(Debug)]
struct Basic {
    bln: u32,
    flt: f32,
    dbl: f64,
    i32: i32,
    i64: i64,
}

fn print_error(future: &mut CassFuture) {
    unsafe {
        let mut message = mem::zeroed();
        let mut message_length = mem::zeroed();
        cass_future_error_message(future, &mut message, &mut message_length);
        println!("Error: {:?}", raw2utf8(message,message_length));
    }
}

fn create_cluster() -> *mut CassCluster {
    unsafe {
        let cluster = cass_cluster_new();
        let host = CString::new("127.0.0.1").unwrap();
        cass_cluster_set_contact_points(cluster, host.as_ptr());
        cluster
    }
}

fn connect_session(session: &mut CassSession, cluster: &CassCluster) -> CassError {
    unsafe {
        let future = cass_session_connect(session, cluster);
        cass_future_wait(future);
        let err = cass_future_error_code(future);
        cass_future_free(future);
        err
    }
}

fn execute_query(session: &mut CassSession, query: &str) -> Result<(), CassError> {
    unsafe {
        let query = CString::new(query).unwrap();
        let statement = cass_statement_new(query.as_ptr(), 0);
        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);
        cass_future_error_code(future);
        let result = match cass_future_error_code(future) {
            CASS_OK => Ok(()),
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);
        result
    }
}

fn insert_into_basic(session: &mut CassSession, key: &str, basic: &Basic) -> Result<(), CassError> {
    unsafe {
        let query = CString::new("INSERT INTO examples.basic (key, bln, flt, dbl, i32, i64) VALUES (?, ?, ?, ?, ?, ?);").unwrap();
        let key = CString::new(key).unwrap();
        let statement = cass_statement_new(query.as_ptr(), 6);

        cass_statement_bind_string(statement, 0, key.as_ptr());
        cass_statement_bind_bool(statement, 1, basic.bln);
        cass_statement_bind_float(statement, 2, basic.flt);
        cass_statement_bind_double(statement, 3, basic.dbl);
        cass_statement_bind_int32(statement, 4, basic.i32);
        cass_statement_bind_int64(statement, 5, basic.i64);

        let future = &mut*cass_session_execute(session, statement);

        cass_future_wait(future);

        let result = match cass_future_error_code(future) {
            CASS_OK => Ok(()),
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);
        result
    }
}

fn prepare_select_from_basic(session: &mut CassSession) -> Result<&CassPrepared, CassError> {
    unsafe {
        let query = CString::new("SELECT * FROM examples.basic WHERE key = ?").unwrap();

        let future = &mut*cass_session_prepare(session, query.as_ptr());
        cass_future_wait(future);

        let result = match cass_future_error_code(future) {
            CASS_OK => {
                let prepared = &*cass_future_get_prepared(future);
                Ok(prepared)
            }
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        result
    }
}

fn select_from_basic(session: &mut CassSession, prepared: &CassPrepared, key: &str, basic: &mut Basic)
                     -> Result<(), CassError> {
    unsafe {
        let statement = cass_prepared_bind(prepared);
        let key = CString::new(key).unwrap();
        cass_statement_bind_string(statement, 0, key.as_ptr());

        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);

        let result = match cass_future_error_code(future) {
            CASS_OK => {
                let result = cass_future_get_result(future);
                let iterator = cass_iterator_from_result(result);

                if cass_iterator_next(iterator) > 0 {
                    let row = cass_iterator_get_row(iterator);

                    cass_value_get_bool(cass_row_get_column(row, 1), &mut basic.bln);
                    cass_value_get_double(cass_row_get_column(row, 2), &mut basic.dbl);
                    cass_value_get_float(cass_row_get_column(row, 3), &mut basic.flt);
                    cass_value_get_int32(cass_row_get_column(row, 4), &mut basic.i32);
                    cass_value_get_int64(cass_row_get_column(row, 5), &mut basic.i64);
                }
                cass_result_free(result);
                cass_iterator_free(iterator);

                Ok(())
            }
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);

        result
    }
}

fn main() {
    unsafe {
        let cluster = &mut*create_cluster();
        let session = cass_session_new();
        let input = Basic { bln: cass_true, flt: 0.001, dbl: 0.0002, i32: 1, i64: 2 };
        let mut output = mem::zeroed();

        if connect_session(&mut*session, cluster) != CASS_OK {
            cass_cluster_free(cluster);
            cass_session_free(session);
            panic!()
        }

        execute_query(&mut*session,
                "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { \
                           'class': 'SimpleStrategy', 'replication_factor': '3' };").unwrap();

        execute_query(&mut*session,
                "CREATE TABLE IF NOT EXISTS examples.basic (key text, \
                                              bln boolean, \
                                              flt float, dbl double,\
                                              i32 int, i64 bigint, \
                                              PRIMARY KEY (key));").unwrap();

        insert_into_basic(&mut*session, "prepared_test", &input).unwrap();

        let prepared = prepare_select_from_basic(&mut*session).unwrap();
        select_from_basic(&mut*session, &prepared, "prepared_test", &mut output).unwrap();

        assert!(input.bln == output.bln);
        assert!(input.flt == output.flt);
        assert!(input.dbl == output.dbl);
        assert!(input.i32 == output.i32);
        assert!(input.i64 == output.i64);
        cass_prepared_free(prepared);
        let close_future = cass_session_close(session);
        cass_future_wait(close_future);
        cass_future_free(close_future);

        cass_cluster_free(cluster);
 // cass_session_free(session);
    }
}
<commit_msg>fixed leak in prepared example<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![allow(float_cmp)]

extern crate cql_bindgen;
extern crate num;

use std::mem;
use std::ffi::CString;

use cql_bindgen::*;

#[derive(Debug)]
struct Basic {
    bln: u32,
    flt: f32,
    dbl: f64,
    i32: i32,
    i64: i64,
}

fn print_error(future: &mut CassFuture) {
    unsafe {
        let mut message = mem::zeroed();
        let mut message_length = mem::zeroed();
        cass_future_error_message(future, &mut message, &mut message_length);
        println!("Error: {:?}", raw2utf8(message,message_length));
    }
}

fn create_cluster() -> *mut CassCluster {
    unsafe {
        let cluster = cass_cluster_new();
        let host = CString::new("127.0.0.1").unwrap();
        cass_cluster_set_contact_points(cluster, host.as_ptr());
        cluster
    }
}

fn connect_session(session: &mut CassSession, cluster: &CassCluster) -> CassError {
    unsafe {
        let future = cass_session_connect(session, cluster);
        cass_future_wait(future);
        let err = cass_future_error_code(future);
        cass_future_free(future);
        err
    }
}

fn execute_query(session: &mut CassSession, query: &str) -> Result<(), CassError> {
    unsafe {
        let query = CString::new(query).unwrap();
        let statement = cass_statement_new(query.as_ptr(), 0);
        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);
        cass_future_error_code(future);
        let result = match cass_future_error_code(future) {
            CASS_OK => Ok(()),
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);
        result
    }
}

fn insert_into_basic(session: &mut CassSession, key: &str, basic: &Basic) -> Result<(), CassError> {
    unsafe {
        let query = CString::new("INSERT INTO examples.basic (key, bln, flt, dbl, i32, i64) VALUES (?, ?, ?, ?, ?, ?);").unwrap();
        let key = CString::new(key).unwrap();
        let statement = cass_statement_new(query.as_ptr(), 6);

        cass_statement_bind_string(statement, 0, key.as_ptr());
        cass_statement_bind_bool(statement, 1, basic.bln);
        cass_statement_bind_float(statement, 2, basic.flt);
        cass_statement_bind_double(statement, 3, basic.dbl);
        cass_statement_bind_int32(statement, 4, basic.i32);
        cass_statement_bind_int64(statement, 5, basic.i64);

        let future = &mut*cass_session_execute(session, statement);

        cass_future_wait(future);

        let result = match cass_future_error_code(future) {
            CASS_OK => Ok(()),
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);
        result
    }
}

fn prepare_select_from_basic(session: &mut CassSession) -> Result<&CassPrepared, CassError> {
    unsafe {
        let query = CString::new("SELECT * FROM examples.basic WHERE key = ?").unwrap();

        let future = &mut*cass_session_prepare(session, query.as_ptr());
        cass_future_wait(future);

        let result = match cass_future_error_code(future) {
            CASS_OK => {
                let prepared = &*cass_future_get_prepared(future);
                Ok(prepared)
            }
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        result
    }
}

fn select_from_basic(session: &mut CassSession, prepared: &CassPrepared, key: &str, basic: &mut Basic)
                     -> Result<(), CassError> {
    unsafe {
        let statement = cass_prepared_bind(prepared);
        let key = CString::new(key).unwrap();
        cass_statement_bind_string(statement, 0, key.as_ptr());

        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);

        let result = match cass_future_error_code(future) {
            CASS_OK => {
                let result = cass_future_get_result(future);
                let iterator = cass_iterator_from_result(result);

                if cass_iterator_next(iterator) > 0 {
                    let row = cass_iterator_get_row(iterator);

                    cass_value_get_bool(cass_row_get_column(row, 1), &mut basic.bln);
                    cass_value_get_double(cass_row_get_column(row, 2), &mut basic.dbl);
                    cass_value_get_float(cass_row_get_column(row, 3), &mut basic.flt);
                    cass_value_get_int32(cass_row_get_column(row, 4), &mut basic.i32);
                    cass_value_get_int64(cass_row_get_column(row, 5), &mut basic.i64);
                }
                cass_result_free(result);
                cass_iterator_free(iterator);

                Ok(())
            }
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);

        result
    }
}

fn main() {
    unsafe {
        let cluster = &mut*create_cluster();
        let session = cass_session_new();
        let input = Basic { bln: cass_true, flt: 0.001, dbl: 0.0002, i32: 1, i64: 2 };
        let mut output = mem::zeroed();

        if connect_session(&mut*session, cluster) != CASS_OK {
            cass_cluster_free(cluster);
            cass_session_free(session);
            panic!()
        }

        execute_query(&mut*session,
                "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { \
                           'class': 'SimpleStrategy', 'replication_factor': '3' };").unwrap();

        execute_query(&mut*session,
                "CREATE TABLE IF NOT EXISTS examples.basic (key text, \
                                              bln boolean, \
                                              flt float, dbl double,\
                                              i32 int, i64 bigint, \
                                              PRIMARY KEY (key));").unwrap();

        insert_into_basic(&mut*session, "prepared_test", &input).unwrap();

        let prepared = prepare_select_from_basic(&mut*session).unwrap();
        select_from_basic(&mut*session, &prepared, "prepared_test", &mut output).unwrap();

        assert!(input.bln == output.bln);
        assert!(input.flt == output.flt);
        assert!(input.dbl == output.dbl);
        assert!(input.i32 == output.i32);
        assert!(input.i64 == output.i64);
        cass_prepared_free(prepared);
        let close_future = cass_session_close(session);
        cass_future_wait(close_future);
        cass_future_free(close_future);

        cass_cluster_free(cluster);
        cass_session_free(session);
    }
}
<|endoftext|>