<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature = "serde")]
use bindgen;
use cc;
use fs_utils::copy::copy_directory;
use glob::glob;

use std::env;
use std::fs;
use std::io::Write;
use std::path::PathBuf;

// these need to be kept in sync with the htslib Makefile
const FILES: &[&str] = &[
    "kfunc.c",
    "knetfile.c",
    "kstring.c",
    "bcf_sr_sort.c",
    "bgzf.c",
    "errmod.c",
    "faidx.c",
    "header.c",
    "hfile.c",
    "hfile_net.c",
    "hts.c",
    "hts_os.c",
    "md5.c",
    "multipart.c",
    "probaln.c",
    "realn.c",
    "regidx.c",
    "region.c",
    "sam.c",
    "synced_bcf_reader.c",
    "vcf_sweep.c",
    "tbx.c",
    "textutils.c",
    "thread_pool.c",
    "vcf.c",
    "vcfutils.c",
    "cram/cram_codecs.c",
    "cram/cram_decode.c",
    "cram/cram_encode.c",
    "cram/cram_external.c",
    "cram/cram_index.c",
    "cram/cram_io.c",
    "cram/cram_samtools.c",
    "cram/cram_stats.c",
    "cram/mFILE.c",
    "cram/open_trace_file.c",
    "cram/pooled_alloc.c",
    "cram/rANS_static.c",
    "cram/string_alloc.c",
];

fn main() {

    let out = PathBuf::from(env::var("OUT_DIR").unwrap());
    if !out.join("htslib").exists() {
        println!("copying...");
        copy_directory("htslib", &out).unwrap();
    }

    let mut cfg = cc::Build::new();

    // default files
    let out_htslib = out.join("htslib");
    let htslib = PathBuf::from("htslib");
    for f in FILES {
        let c_file = out_htslib.join(f);
        cfg.file(&c_file);
        println!("cargo:rerun-if-changed={}", htslib.join(f).display());
    }

    cfg.include(out.join("htslib"));

    let want_static = cfg!(feature = "static") || env::var("HTS_STATIC").is_ok();

    if want_static {
        cfg.warnings(true).static_flag(true).pic(true);
    } else {
        cfg.warnings(true).static_flag(false).pic(true);
    }

    if let Ok(z_inc) = env::var("DEP_Z_INCLUDE") {
        cfg.include(z_inc);
    }

    // We build a config.h ourselves, rather than rely on Makefile or ./configure
    let mut config_lines = vec![
        "/* Default config.h generated by build.rs */",
        "#define HAVE_DRAND48 1",
    ];

    let use_bzip2 = env::var("CARGO_FEATURE_BZIP2").is_ok();
    if use_bzip2 {
         if let Ok(inc) = env::var("DEP_BZIP2_ROOT")
        .map(PathBuf::from)
        .map(|path| path.join("include"))
        {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBBZ2 1");
        }
    }

    let use_libdeflate = env::var("CARGO_FEATURE_LIBDEFLATE").is_ok();
    if use_libdeflate {
        if let Ok(inc) = env::var("DEP_LIBDEFLATE_INCLUDE").map(PathBuf::from) {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBDEFLATE 1");
        } else {
            panic!("no DEP_LIBDEFLATE_INCLUDE");
        }
    }

    let use_lzma = env::var("CARGO_FEATURE_LZMA").is_ok();
    if use_lzma {
        if let Ok(inc) = env::var("DEP_LZMA_INCLUDE").map(PathBuf::from) {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBBZ2 1");
            config_lines.push("#ifndef __APPLE__");
            config_lines.push("#define HAVE_LZMA_H 1");
            config_lines.push("#endif");
        }
    }

    let use_curl = env::var("CARGO_FEATURE_CURL").is_ok();
    if use_curl {
        if let Ok(inc) = env::var("DEP_CURL_INCLUDE").map(PathBuf::from) {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBCURL 1");
            cfg.file("htslib/hfile_libcurl.c");
            println!("cargo:rerun-if-changed=htslib/hfile_libcurl.c");

            #[cfg(target_os="macos")]
            {
                // Use builtin MacOS CommonCrypto HMAC
                config_lines.push("#define HAVE_COMMONCRYPTO 1");
            }

            #[cfg(not(target_os="macos"))]
            {
                if let Ok(inc) = env::var("DEP_OPENSSL_INCLUDE").map(PathBuf::from) {
                    // Must use hmac from libcrypto in openssl
                    cfg.include(inc);
                    config_lines.push("#define HAVE_HMAC 1");
                } else {
                    panic!("No OpenSSL dependency -- need OpenSSL includes");
                }
            }
        }
    }

    let use_gcs = env::var("CARGO_FEATURE_GCS").is_ok();
    if use_gcs {
        config_lines.push("#define ENABLE_GCS 1");
        cfg.file("htslib/hfile_gcs.c");
        println!("cargo:rerun-if-changed=htslib/hfile_gcs.c");
    }

    let use_s3 = env::var("CARGO_FEATURE_S3").is_ok();
    if use_s3 {
        config_lines.push("#define ENABLE_S3 1");
        cfg.file("htslib/hfile_s3.c");
        println!("cargo:rerun-if-changed=htslib/hfile_s3.c");
        cfg.file("htslib/hfile_s3_write.c");
        println!("cargo:rerun-if-changed=htslib/hfile_s3_write.c");
    }

    // write out config.h which controls the options htslib will use
    {
        let mut f = std::fs::File::create(out.join("htslib").join("config.h")).unwrap();
        for l in config_lines {
            writeln!(&mut f, "{}", l).unwrap();
        };
    }

    // write out version.h
    {
        let version = std::process::Command::new(out.join("htslib").join("version.sh"))
                             .output()
                             .expect("failed to execute process");
        let version_str = std::str::from_utf8(&version.stdout).unwrap().trim();

        let mut f = std::fs::File::create(out.join("htslib").join("version.h")).unwrap();
        writeln!(&mut f, "#define HTS_VERSION_TEXT \"{}\"", version_str).unwrap();
    }

    cfg.file("wrapper.c");
    cfg.compile("hts");

    // If bindgen is enabled, use it
    #[cfg(feature = "bindgen")]
    {
        bindgen::Builder::default()
            .header("wrapper.h")
            .generate_comments(false)
            .blacklist_function("strtold")
            .blacklist_type("max_align_t")
            .generate()
            .expect("Unable to generate bindings.")
            .write_to_file(out.join("bindings.rs"))
            .expect("Could not write bindings.");
    }

    // If no bindgen, use pre-built bindings
    #[cfg(all(not(feature = "bindgen"), target_os="macos"))]
    {
        fs::copy("osx_prebuilt_bindings.rs", out.join("bindings.rs"))
            .expect("couldn't copy prebuilt bindings");
        println!("cargo:rerun-if-changed=osx_prebuilt_bindings.rs");
    }

    #[cfg(all(not(feature = "bindgen"), target_os="linux"))]
    {
        fs::copy("linux_prebuilt_bindings.rs", out.join("bindings.rs"))
            .expect("couldn't copy prebuilt bindings");
        println!("cargo:rerun-if-changed=linux_prebuilt_bindings.rs");
    }

    let include = out.join("include");
    fs::create_dir_all(&include).unwrap();
    if include.join("htslib").exists() {
        fs::remove_dir_all(include.join("htslib")).expect("remove exist include dir");
    }
    copy_directory(out.join("htslib").join("htslib"), &include).unwrap();

    println!("cargo:root={}", out.display());
    println!("cargo:include={}", include.display());
    println!("cargo:libdir={}", out.display());
    println!("cargo:rerun-if-changed=wrapper.c");
    println!("cargo:rerun-if-changed=wrapper.h");

    let globs = std::iter::empty()
        .chain(glob("htslib/*.[h]").unwrap())
        .chain(glob("htslib/cram/*.[h]").unwrap())
        .chain(glob("htslib/htslib/*.h").unwrap())
        .chain(glob("htslib/os/*.[h]").unwrap())
        .filter_map(Result::ok);
    for htsfile in globs {
        println!("cargo:rerun-if-changed={}", htsfile.display());
    }

    // Note: config.h is a function of the cargo features. Any feature change will
    // cause build.rs to re-run, so don't re-run on that change.
    //println!("cargo:rerun-if-changed=htslib/config.h");
}<commit_msg>fix detection of stale htslib files (#273)<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(feature = "serde")]
use bindgen;
use cc;
use fs_utils::copy::copy_directory;
use glob::glob;

use std::env;
use std::fs;
use std::io::Write;
use std::path::PathBuf;

// these need to be kept in sync with the htslib Makefile
const FILES: &[&str] = &[
    "kfunc.c",
    "knetfile.c",
    "kstring.c",
    "bcf_sr_sort.c",
    "bgzf.c",
    "errmod.c",
    "faidx.c",
    "header.c",
    "hfile.c",
    "hfile_net.c",
    "hts.c",
    "hts_os.c",
    "md5.c",
    "multipart.c",
    "probaln.c",
    "realn.c",
    "regidx.c",
    "region.c",
    "sam.c",
    "synced_bcf_reader.c",
    "vcf_sweep.c",
    "tbx.c",
    "textutils.c",
    "thread_pool.c",
    "vcf.c",
    "vcfutils.c",
    "cram/cram_codecs.c",
    "cram/cram_decode.c",
    "cram/cram_encode.c",
    "cram/cram_external.c",
    "cram/cram_index.c",
    "cram/cram_io.c",
    "cram/cram_samtools.c",
    "cram/cram_stats.c",
    "cram/mFILE.c",
    "cram/open_trace_file.c",
    "cram/pooled_alloc.c",
    "cram/rANS_static.c",
    "cram/string_alloc.c",
];

fn main() {

    let out = PathBuf::from(env::var("OUT_DIR").unwrap());
    let htslib_copy = out.join("htslib");

    if htslib_copy.exists() {
        std::fs::remove_dir_all(htslib_copy).unwrap();
    }
    copy_directory("htslib", &out).unwrap();

    let mut cfg = cc::Build::new();

    // default files
    let out_htslib = out.join("htslib");
    let htslib = PathBuf::from("htslib");
    for f in FILES {
        let c_file = out_htslib.join(f);
        cfg.file(&c_file);
        println!("cargo:rerun-if-changed={}", htslib.join(f).display());
    }

    cfg.include(out.join("htslib"));

    let want_static = cfg!(feature = "static") || env::var("HTS_STATIC").is_ok();

    if want_static {
        cfg.warnings(true).static_flag(true).pic(true);
    } else {
        cfg.warnings(true).static_flag(false).pic(true);
    }

    if let Ok(z_inc) = env::var("DEP_Z_INCLUDE") {
        cfg.include(z_inc);
    }

    // We build a config.h ourselves, rather than rely on Makefile or ./configure
    let mut config_lines = vec![
        "/* Default config.h generated by build.rs */",
        "#define HAVE_DRAND48 1",
    ];

    let use_bzip2 = env::var("CARGO_FEATURE_BZIP2").is_ok();
    if use_bzip2 {
         if let Ok(inc) = env::var("DEP_BZIP2_ROOT")
        .map(PathBuf::from)
        .map(|path| path.join("include"))
        {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBBZ2 1");
        }
    }

    let use_libdeflate = env::var("CARGO_FEATURE_LIBDEFLATE").is_ok();
    if use_libdeflate {
        if let Ok(inc) = env::var("DEP_LIBDEFLATE_INCLUDE").map(PathBuf::from) {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBDEFLATE 1");
        } else {
            panic!("no DEP_LIBDEFLATE_INCLUDE");
        }
    }

    let use_lzma = env::var("CARGO_FEATURE_LZMA").is_ok();
    if use_lzma {
        if let Ok(inc) = env::var("DEP_LZMA_INCLUDE").map(PathBuf::from) {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBBZ2 1");
            config_lines.push("#ifndef __APPLE__");
            config_lines.push("#define HAVE_LZMA_H 1");
            config_lines.push("#endif");
        }
    }

    let use_curl = env::var("CARGO_FEATURE_CURL").is_ok();
    if use_curl {
        if let Ok(inc) = env::var("DEP_CURL_INCLUDE").map(PathBuf::from) {
            cfg.include(inc);
            config_lines.push("#define HAVE_LIBCURL 1");
            cfg.file("htslib/hfile_libcurl.c");
            println!("cargo:rerun-if-changed=htslib/hfile_libcurl.c");

            #[cfg(target_os="macos")]
            {
                // Use builtin MacOS CommonCrypto HMAC
                config_lines.push("#define HAVE_COMMONCRYPTO 1");
            }

            #[cfg(not(target_os="macos"))]
            {
                if let Ok(inc) = env::var("DEP_OPENSSL_INCLUDE").map(PathBuf::from) {
                    // Must use hmac from libcrypto in openssl
                    cfg.include(inc);
                    config_lines.push("#define HAVE_HMAC 1");
                } else {
                    panic!("No OpenSSL dependency -- need OpenSSL includes");
                }
            }
        }
    }

    let use_gcs = env::var("CARGO_FEATURE_GCS").is_ok();
    if use_gcs {
        config_lines.push("#define ENABLE_GCS 1");
        cfg.file("htslib/hfile_gcs.c");
        println!("cargo:rerun-if-changed=htslib/hfile_gcs.c");
    }

    let use_s3 = env::var("CARGO_FEATURE_S3").is_ok();
    if use_s3 {
        config_lines.push("#define ENABLE_S3 1");
        cfg.file("htslib/hfile_s3.c");
        println!("cargo:rerun-if-changed=htslib/hfile_s3.c");
        cfg.file("htslib/hfile_s3_write.c");
        println!("cargo:rerun-if-changed=htslib/hfile_s3_write.c");
    }

    // write out config.h which controls the options htslib will use
    {
        let mut f = std::fs::File::create(out.join("htslib").join("config.h")).unwrap();
        for l in config_lines {
            writeln!(&mut f, "{}", l).unwrap();
        };
    }

    // write out version.h
    {
        let version = std::process::Command::new(out.join("htslib").join("version.sh"))
                             .output()
                             .expect("failed to execute process");
        let version_str = std::str::from_utf8(&version.stdout).unwrap().trim();

        let mut f = std::fs::File::create(out.join("htslib").join("version.h")).unwrap();
        writeln!(&mut f, "#define HTS_VERSION_TEXT \"{}\"", version_str).unwrap();
    }

    cfg.file("wrapper.c");
    cfg.compile("hts");

    // If bindgen is enabled, use it
    #[cfg(feature = "bindgen")]
    {
        bindgen::Builder::default()
            .header("wrapper.h")
            .generate_comments(false)
            .blacklist_function("strtold")
            .blacklist_type("max_align_t")
            .generate()
            .expect("Unable to generate bindings.")
            .write_to_file(out.join("bindings.rs"))
            .expect("Could not write bindings.");
    }

    // If no bindgen, use pre-built bindings
    #[cfg(all(not(feature = "bindgen"), target_os="macos"))]
    {
        fs::copy("osx_prebuilt_bindings.rs", out.join("bindings.rs"))
            .expect("couldn't copy prebuilt bindings");
        println!("cargo:rerun-if-changed=osx_prebuilt_bindings.rs");
    }

    #[cfg(all(not(feature = "bindgen"), target_os="linux"))]
    {
        fs::copy("linux_prebuilt_bindings.rs", out.join("bindings.rs"))
            .expect("couldn't copy prebuilt bindings");
        println!("cargo:rerun-if-changed=linux_prebuilt_bindings.rs");
    }

    let include = out.join("include");
    fs::create_dir_all(&include).unwrap();
    if include.join("htslib").exists() {
        fs::remove_dir_all(include.join("htslib")).expect("remove exist include dir");
    }
    copy_directory(out.join("htslib").join("htslib"), &include).unwrap();

    println!("cargo:root={}", out.display());
    println!("cargo:include={}", include.display());
    println!("cargo:libdir={}", out.display());
    println!("cargo:rerun-if-changed=wrapper.c");
    println!("cargo:rerun-if-changed=wrapper.h");

    let globs = std::iter::empty()
        .chain(glob("htslib/*.[h]").unwrap())
        .chain(glob("htslib/cram/*.[h]").unwrap())
        .chain(glob("htslib/htslib/*.h").unwrap())
        .chain(glob("htslib/os/*.[h]").unwrap())
        .filter_map(Result::ok);
    for htsfile in globs {
        println!("cargo:rerun-if-changed={}", htsfile.display());
    }

    // Note: config.h is a function of the cargo features. Any feature change will
    // cause build.rs to re-run, so don't re-run on that change.
    //println!("cargo:rerun-if-changed=htslib/config.h");
}<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;

#[derive(Debug)]
enum ParameterMode {
  Position,
  Immediate
}

#[derive(Debug)]
enum OperationType {
  Add,
  Multiply,
  Input,
  Output,
  JumpIfTrue,
  JumpIfFalse,
  LessThan,
  Equals,
  Halt
}

#[derive(Debug)]
struct Instruction {
  operation: OperationType,
  inputs: Vec<(ParameterMode, i32)>
}

fn get_input() -> std::io::Result<String> {
  let mut file = File::open("05.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn parse_instruction(numbers: &[i32]) -> Instruction {
  let instruction_code = numbers[0];
  let op_code = instruction_code % 100;

  let (operation, inputs_count) = match op_code {
    1 => (OperationType::Add, 3),
    2 => (OperationType::Multiply, 3),
    3 => (OperationType::Input, 1),
    4 => (OperationType::Output, 1),
    5 => (OperationType::JumpIfTrue, 2),
    6 => (OperationType::JumpIfFalse, 2),
    7 => (OperationType::LessThan, 3),
    8 => (OperationType::Equals, 3),
    99 => (OperationType::Halt, 0),
    _ => panic!()
  };

  let get_parameter_mode = |i| {
    match (instruction_code - op_code as i32) / 10i32.pow(2 + i as u32) % 10 {
      0 => ParameterMode::Position,
      1 => ParameterMode::Immediate,
      _ => panic!()
    }
  };

  Instruction {
    operation,
    inputs: (0..inputs_count)
      .map(|i| (get_parameter_mode(i), numbers[i + 1]))
      .collect()
  }
}

fn run_program(program: &mut Vec<i32>, input: i32) -> Vec<i32> {
  let mut result = vec![];
  let mut pointer = 0;

  while pointer < program.len() {
    let init_pointer = pointer;
    let instruction = parse_instruction(&program[pointer..]);

    let (target_value, target_index) = {
      let get_input = |i| match instruction.inputs[i] {
        (ParameterMode::Position, j) => program[j as usize],
        (ParameterMode::Immediate, value) => value
      };

      match instruction.operation {
        OperationType::Add => (
          Some(get_input(0) + get_input(1)),
          Some(instruction.inputs[2].1 as usize)
        ),
        OperationType::Multiply => (
          Some(get_input(0) * get_input(1)),
          Some(instruction.inputs[2].1 as usize)
        ),
        OperationType::Input => (
          Some(input),
          Some(instruction.inputs[0].1 as usize)
        ),
        OperationType::Output => (
          Some(get_input(0)),
          None
        ),
        OperationType::JumpIfTrue => {
          if get_input(0) != 0 { pointer = get_input(1) as usize; }
          (None, None)
        },
        OperationType::JumpIfFalse => {
          if get_input(0) == 0 { pointer = get_input(1) as usize; }
          (None, None)
        }
        OperationType::LessThan => (
          Some(if get_input(0) < get_input(1) { 1 } else { 0 }),
          Some(instruction.inputs[2].1 as usize)
        ),
        OperationType::Equals => (
          Some(if get_input(0) == get_input(1) { 1 } else { 0 }),
          Some(instruction.inputs[2].1 as usize)
        ),
        OperationType::Halt => break
      }
    };

    if let Some(target_value) = target_value {
      if let Some(target_index) = target_index {
        program[target_index] = target_value;
      } else {
        result.push(target_value);
      }
    }

    if pointer == init_pointer {
      pointer += instruction.inputs.len() + 1;
    }
  }

  result
}

fn main() {
  let input = get_input().unwrap();
  let numbers = input.split(',')
    .filter_map(|x| x.trim().parse::<i32>().ok())
    .collect::<Vec<_>>();

  let output = run_program(&mut numbers.clone(), 1);
  println!("Part 1: {}", output.last().unwrap());

  let output = run_program(&mut numbers.clone(), 5);
  println!("Part 2: {}", output.last().unwrap());
}
<commit_msg>Simplify code<commit_after>use std::fs::File;
use std::io::prelude::*;

#[derive(Debug)]
enum ParameterMode {
  Position,
  Immediate
}

#[derive(Debug)]
enum OperationType {
  Add,
  Multiply,
  Input,
  Output,
  JumpIfTrue,
  JumpIfFalse,
  LessThan,
  Equals,
  Halt
}

#[derive(Debug)]
struct Instruction {
  operation: OperationType,
  inputs: Vec<(ParameterMode, i32)>
}

fn get_input() -> std::io::Result<String> {
  let mut file = File::open("05.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn parse_instruction(numbers: &[i32]) -> Instruction {
  let instruction_code = numbers[0];
  let op_code = instruction_code % 100;

  let (operation, inputs_count) = match op_code {
    1 => (OperationType::Add, 3),
    2 => (OperationType::Multiply, 3),
    3 => (OperationType::Input, 1),
    4 => (OperationType::Output, 1),
    5 => (OperationType::JumpIfTrue, 2),
    6 => (OperationType::JumpIfFalse, 2),
    7 => (OperationType::LessThan, 3),
    8 => (OperationType::Equals, 3),
    99 => (OperationType::Halt, 0),
    _ => panic!()
  };

  let get_parameter_mode = |i| {
    match (instruction_code - op_code) / 10i32.pow(2 + i as u32) % 10 {
      0 => ParameterMode::Position,
      1 => ParameterMode::Immediate,
      _ => panic!()
    }
  };

  Instruction {
    operation,
    inputs: (0..inputs_count)
      .map(|i| (get_parameter_mode(i), numbers[i + 1]))
      .collect()
  }
}

fn run_program(program: &mut Vec<i32>, input: i32) -> Vec<i32> {
  let mut result = vec![];
  let mut pointer = 0;

  while pointer < program.len() {
    let init_pointer = pointer;
    let instruction = parse_instruction(&program[pointer..]);

    let (target_value, target_index) = {
      let get_input = |i| match instruction.inputs[i] {
        (ParameterMode::Position, j) => program[j as usize],
        (ParameterMode::Immediate, value) => value
      };

      let mut jump = |condition, i| {
        if condition {
          pointer = get_input(i) as usize;
        }

        (None, None)
      };

      let (target_value, output_index) = match instruction.operation {
        OperationType::Add => (Some(get_input(0) + get_input(1)), Some(2)),
        OperationType::Multiply => (Some(get_input(0) * get_input(1)), Some(2)),
        OperationType::Input => (Some(input), Some(0)),
        OperationType::Output => (Some(get_input(0)), None),
        OperationType::LessThan => (Some((get_input(0) < get_input(1)) as i32), Some(2)),
        OperationType::Equals => (Some((get_input(0) == get_input(1)) as i32), Some(2)),
        OperationType::JumpIfTrue => jump(get_input(0) != 0, 1),
        OperationType::JumpIfFalse => jump(get_input(0) == 0, 1),
        OperationType::Halt => break
      };

      (target_value, output_index.map(|i| instruction.inputs[i].1 as usize))
    };

    if let Some(target_value) = target_value {
      if let Some(target_index) = target_index {
        program[target_index] = target_value;
      } else {
        result.push(target_value);
      }
    }

    if pointer == init_pointer {
      pointer += instruction.inputs.len() + 1;
    }
  }

  result
}

fn main() {
  let input = get_input().unwrap();
  let numbers = input.split(',')
    .filter_map(|x| x.trim().parse::<i32>().ok())
    .collect::<Vec<_>>();

  let output = run_program(&mut numbers.clone(), 1);
  println!("Part 1: {}", output.last().unwrap());

  let output = run_program(&mut numbers.clone(), 5);
  println!("Part 2: {}", output.last().unwrap());
}
<|endoftext|>


<commit_before>//! Lock file management

use errors::*;

use std::fs::{OpenOptions, remove_file};
use std::io::prelude::*;
use std::path::PathBuf;

#[derive(Clone)]
pub struct Lock {
    path: PathBuf,
}

impl Lock {
    pub fn create(path: PathBuf) -> Result<Self> {
        // Create a lock file
        let mut file = OpenOptions::new()
            .write(true)
            .create_new(true)
            .open(&path)
            .chain_err(|| ErrorKind::LockFileCreate(path.clone()))?;

        // Write the process id into the lock file
        let pid = format!(
            "{}\n",
            unsafe { ::libc::getpid() }
        );
        file.write_all(pid.as_bytes())
            .chain_err(|| ErrorKind::LockFileWrite(path.clone()))?;

        // Create struct
        let lock = Lock { path };
        Ok(lock)
    }

    pub fn handle_sigint(self) -> Result<Self> {
        // Create a clone
        let twin = self.clone();

        // Setup SIGINT handler
        // TODO Replace ctrlc by tokio-signal?!
        ::ctrlc::set_handler(move || {
            if let Err(err) = twin.release_ref() {
                handle(&err);
            }
            ::std::process::exit(0);
        })
            .chain_err(|| ErrorKind::LockFileSetupSigintHandler)?;

        // Return self
        Ok(self)
    }

    pub fn release(self) { }

    fn release_ref(&self) -> Result<()> {
        // Remove the lock file
        remove_file(&self.path)
            .chain_err(|| ErrorKind::LockFileRemove(self.path.clone()))?;

        Ok(())
    }
}

impl Drop for Lock {
    fn drop(&mut self) {
        if let Err(err) = self.release_ref() {
            handle(&err);
        }
    }
}
<commit_msg>Bugfix<commit_after>//! Lock file management

use errors::*;

use std::fs::{OpenOptions, remove_file};
use std::io::prelude::*;
use std::path::PathBuf;

pub struct Lock {
    path: PathBuf,
}

impl Lock {
    pub fn create(path: PathBuf) -> Result<Self> {
        // Create a lock file
        let mut file = OpenOptions::new()
            .write(true)
            .create_new(true)
            .open(&path)
            .chain_err(|| ErrorKind::LockFileCreate(path.clone()))?;

        // Write the process id into the lock file
        let pid = format!(
            "{}\n",
            unsafe { ::libc::getpid() }
        );
        file.write_all(pid.as_bytes())
            .chain_err(|| ErrorKind::LockFileWrite(path.clone()))?;

        // Create struct
        let lock = Lock { path };
        Ok(lock)
    }

    pub fn handle_sigint(self) -> Result<Self> {
        // Create a clone
        //
        // WARNING: Do not derive Clone for Lock in order to simplify this operation since it is
        // not a good idea to have a twin in the wild. The relation between a Lock and its lock
        // file should be 1-to-1 because a lock -- when going out of scope -- removes the lock
        // file. Having a clone will result in a runtime error as soon as the second lock goes out
        // of scope and tries to remove the -- no longer existing -- lock file.
        let twin = Lock { path: self.path.clone() };

        // Setup SIGINT handler
        // TODO Replace ctrlc by tokio-signal?!
        ::ctrlc::set_handler(move || {
            if let Err(err) = twin.release_ref() {
                handle(&err);
            }
            ::std::process::exit(0);
        })
            .chain_err(|| ErrorKind::LockFileSetupSigintHandler)?;

        // Return self
        Ok(self)
    }

    pub fn release(self) { }

    fn release_ref(&self) -> Result<()> {
        // Remove the lock file
        remove_file(&self.path)
            .chain_err(|| ErrorKind::LockFileRemove(self.path.clone()))?;

        Ok(())
    }
}

impl Drop for Lock {
    fn drop(&mut self) {
        if let Err(err) = self.release_ref() {
            handle(&err);
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use std::cmp::Ordering;

pointer_ord!(WordInstance);

impl WordInstance {
    pub fn next_instance(&self) -> Option<InstanceCell> {
        let mb = self.message.borrow();
        mb.instances.get((self.index as isize + 1) as usize).cloned()
    }

    pub fn prev_instance(&self) -> Option<InstanceCell> {
        let mb = self.message.borrow();
        mb.instances.get((self.index as isize - 1) as usize).cloned()
    }

    pub fn precoincidence_neighbors(ins: (&InstanceCell, &InstanceCell), min_edge_distance: usize) -> bool {
        let bs = (ins.0.borrow(), ins.1.borrow());
        let ms = (bs.0.message.borrow(), bs.1.message.borrow());
        let preins = (ms.0.instances.get((bs.0.index as isize - 1) as usize),
                ms.1.instances.get((bs.1.index as isize - 1) as usize));

        match preins {
            // There are two words
            (Some(i0), Some(i1)) => {
                if Category::are_postcocategories((&i0.borrow().category, &i1.borrow().category)) {
                    true
                } else if i0.borrow().word == i1.borrow().word {
                    WordInstance::precoincidence_neighbors((i0, i1), min_edge_distance.saturating_sub(1))
                } else {
                    false
                }
            },
            // End of the sentence is only a match if we had prior matches
            (None, None) => min_edge_distance == 0,
            _ => false,
        }
    }

    pub fn postcoincidence_neighbors(ins: (&InstanceCell, &InstanceCell), min_edge_distance: usize) -> bool {
        let bs = (ins.0.borrow(), ins.1.borrow());
        let ms = (bs.0.message.borrow(), bs.1.message.borrow());
        let postins = (ms.0.instances.get((bs.0.index as isize + 1) as usize),
                ms.1.instances.get((bs.1.index as isize + 1) as usize));

        match postins {
            // There are two words
            (Some(i0), Some(i1)) => {
                if Category::are_precocategories((&i0.borrow().category, &i1.borrow().category)) {
                    true
                } else if i0.borrow().word == i1.borrow().word {
                    WordInstance::postcoincidence_neighbors((i0, i1), min_edge_distance.saturating_sub(1))
                } else {
                    false
                }
            },
            // End of the sentence is only a match if this can be the edge
            (None, None) => min_edge_distance == 0,
            _ => false,
        }
    }
}
<commit_msg>extend cocategory creation to take into account both kinds of cocategories regardless of the type being created<commit_after>use super::*;
use std::cmp::Ordering;

pointer_ord!(WordInstance);

impl WordInstance {
    pub fn next_instance(&self) -> Option<InstanceCell> {
        let mb = self.message.borrow();
        mb.instances.get((self.index as isize + 1) as usize).cloned()
    }

    pub fn prev_instance(&self) -> Option<InstanceCell> {
        let mb = self.message.borrow();
        mb.instances.get((self.index as isize - 1) as usize).cloned()
    }

    pub fn precoincidence_neighbors(ins: (&InstanceCell, &InstanceCell), min_edge_distance: usize) -> bool {
        let bs = (ins.0.borrow(), ins.1.borrow());
        let ms = (bs.0.message.borrow(), bs.1.message.borrow());
        let preins = (ms.0.instances.get((bs.0.index as isize - 1) as usize),
                ms.1.instances.get((bs.1.index as isize - 1) as usize));

        match preins {
            // There are two words
            (Some(i0), Some(i1)) => {
                if Category::are_postcocategories((&i0.borrow().category, &i1.borrow().category)) ||
                    Category::are_precocategories((&i0.borrow().category, &i1.borrow().category)) {
                    true
                } else if i0.borrow().word == i1.borrow().word {
                    WordInstance::precoincidence_neighbors((i0, i1), min_edge_distance.saturating_sub(1))
                } else {
                    false
                }
            },
            // End of the sentence is only a match if we had prior matches
            (None, None) => min_edge_distance == 0,
            _ => false,
        }
    }

    pub fn postcoincidence_neighbors(ins: (&InstanceCell, &InstanceCell), min_edge_distance: usize) -> bool {
        let bs = (ins.0.borrow(), ins.1.borrow());
        let ms = (bs.0.message.borrow(), bs.1.message.borrow());
        let postins = (ms.0.instances.get((bs.0.index as isize + 1) as usize),
                ms.1.instances.get((bs.1.index as isize + 1) as usize));

        match postins {
            // There are two words
            (Some(i0), Some(i1)) => {
                if Category::are_precocategories((&i0.borrow().category, &i1.borrow().category)) ||
                    Category::are_postcocategories((&i0.borrow().category, &i1.borrow().category)) {
                    true
                } else if i0.borrow().word == i1.borrow().word {
                    WordInstance::postcoincidence_neighbors((i0, i1), min_edge_distance.saturating_sub(1))
                } else {
                    false
                }
            },
            // End of the sentence is only a match if this can be the edge
            (None, None) => min_edge_distance == 0,
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>use config;

use infer_schema_internals::*;
use serde::de::{self, MapAccess, Visitor};
use serde::{Deserialize, Deserializer};
use std::error::Error;
use std::fmt::{self, Display, Formatter, Write};
use std::fs::File;
use std::io::{self, Write as IoWrite};
use std::path::Path;
use std::process::Command;
use tempfile::NamedTempFile;

pub enum Filtering {
    OnlyTables(Vec<TableName>),
    ExceptTables(Vec<TableName>),
    None,
}

impl Default for Filtering {
    fn default() -> Self {
        Filtering::None
    }
}

impl Filtering {
    pub fn should_ignore_table(&self, name: &TableName) -> bool {
        use self::Filtering::*;

        match *self {
            OnlyTables(ref names) => !names.contains(name),
            ExceptTables(ref names) => names.contains(name),
            None => false,
        }
    }
}

pub fn run_print_schema<W: IoWrite>(
    database_url: &str,
    config: &config::PrintSchema,
    output: &mut W,
) -> Result<(), Box<dyn Error>> {
    let tempfile = NamedTempFile::new()?;
    let file = tempfile.reopen()?;
    output_schema(database_url, config, file, tempfile.path())?;

    // patch "replaces" our tempfile, meaning the old handle
    // does not include the patched output.
    let mut file = File::open(tempfile.path())?;
    io::copy(&mut file, output)?;
    Ok(())
}

pub fn output_schema(
    database_url: &str,
    config: &config::PrintSchema,
    mut out: File,
    out_path: &Path,
) -> Result<(), Box<dyn Error>> {
    let table_names = load_table_names(database_url, config.schema_name())?
        .into_iter()
        .filter(|t| !config.filter.should_ignore_table(t))
        .collect::<Vec<_>>();
    let foreign_keys = load_foreign_key_constraints(database_url, config.schema_name())?;
    let foreign_keys =
        remove_unsafe_foreign_keys_for_codegen(database_url, &foreign_keys, &table_names);
    let table_data = table_names
        .into_iter()
        .map(|t| load_table_data(database_url, t))
        .collect::<Result<_, Box<dyn Error>>>()?;
    let definitions = TableDefinitions {
        tables: table_data,
        fk_constraints: foreign_keys,
        include_docs: config.with_docs,
        import_types: config.import_types(),
    };

    if let Some(schema_name) = config.schema_name() {
        write!(out, "{}", ModuleDefinition(schema_name, definitions))?;
    } else {
        write!(out, "{}", definitions)?;
    }

    if let Some(ref patch_file) = config.patch_file {
        let output = Command::new("patch")
            .arg(out_path)
            .arg(patch_file)
            .output()?;
        if !output.status.success() {
            let stdout = String::from_utf8_lossy(&output.stdout);
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(format!(
                "Failed to apply schema patch. stdout: {} stderr: {}",
                stdout, stderr,
            )
            .into());
        }
    }

    Ok(())
}

struct ModuleDefinition<'a>(&'a str, TableDefinitions<'a>);

impl<'a> Display for ModuleDefinition<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        {
            let mut out = PadAdapter::new(f);
            writeln!(out, "pub mod {} {{", self.0)?;
            write!(out, "{}", self.1)?;
        }
        writeln!(f, "}}")?;
        Ok(())
    }
}

struct TableDefinitions<'a> {
    tables: Vec<TableData>,
    fk_constraints: Vec<ForeignKeyConstraint>,
    include_docs: bool,
    import_types: Option<&'a [String]>,
}

impl<'a> Display for TableDefinitions<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let mut is_first = true;
        for table in &self.tables {
            if is_first {
                is_first = false;
            } else {
                writeln!(f)?;
            }
            writeln!(
                f,
                "{}",
                TableDefinition {
                    table,
                    include_docs: self.include_docs,
                    import_types: self.import_types,
                }
            )?;
        }

        if !self.fk_constraints.is_empty() {
            writeln!(f)?;
        }

        for foreign_key in &self.fk_constraints {
            writeln!(f, "{}", Joinable(foreign_key))?;
        }

        if self.tables.len() > 1 {
            write!(f, "\nallow_tables_to_appear_in_same_query!(")?;
            {
                let mut out = PadAdapter::new(f);
                writeln!(out)?;
                for table in &self.tables {
                    writeln!(out, "{},", table.name.name)?;
                }
            }
            writeln!(f, ");")?;
        }

        Ok(())
    }
}

struct TableDefinition<'a> {
    table: &'a TableData,
    import_types: Option<&'a [String]>,
    include_docs: bool,
}

impl<'a> Display for TableDefinition<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "table! {{")?;
        {
            let mut out = PadAdapter::new(f);
            writeln!(out)?;

            if let Some(types) = self.import_types {
                for import in types {
                    writeln!(out, "use {};", import)?;
                }
                writeln!(out)?;
            }

            if self.include_docs {
                for d in self.table.docs.lines() {
                    writeln!(out, "///{}{}", if d.is_empty() { "" } else { " " }, d)?;
                }
            }

            write!(out, "{} (", self.table.name)?;
            for (i, pk) in self.table.primary_key.iter().enumerate() {
                if i != 0 {
                    write!(out, ", ")?;
                }
                write!(out, "{}", pk)?;
            }

            write!(
                out,
                ") {}",
                ColumnDefinitions {
                    columns: &self.table.column_data,
                    include_docs: self.include_docs,
                }
            )?;
        }
        write!(f, "}}")?;
        Ok(())
    }
}

struct ColumnDefinitions<'a> {
    columns: &'a [ColumnDefinition],
    include_docs: bool,
}

impl<'a> Display for ColumnDefinitions<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        {
            let mut out = PadAdapter::new(f);
            writeln!(out, "{{")?;
            for column in self.columns {
                if self.include_docs {
                    for d in column.docs.lines() {
                        writeln!(out, "///{}{}", if d.is_empty() { "" } else { " " }, d)?;
                    }
                }
                if let Some(ref rust_name) = column.rust_name {
                    writeln!(out, r#"#[sql_name = "{}"]"#, column.sql_name)?;
                    writeln!(out, "{} -> {},", rust_name, column.ty)?;
                } else {
                    writeln!(out, "{} -> {},", column.sql_name, column.ty)?;
                }
            }
        }
        writeln!(f, "}}")?;
        Ok(())
    }
}

struct Joinable<'a>(&'a ForeignKeyConstraint);

impl<'a> Display for Joinable<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(
            f,
            "joinable!({} -> {} ({}));",
            self.0.child_table.name, self.0.parent_table.name, self.0.foreign_key_rust_name,
        )
    }
}

/// Lifted directly from libcore/fmt/builders.rs
struct PadAdapter<'a, 'b: 'a> {
    fmt: &'a mut Formatter<'b>,
    on_newline: bool,
}

impl<'a, 'b: 'a> PadAdapter<'a, 'b> {
    fn new(fmt: &'a mut Formatter<'b>) -> PadAdapter<'a, 'b> {
        PadAdapter {
            fmt,
            on_newline: false,
        }
    }
}

impl<'a, 'b: 'a> Write for PadAdapter<'a, 'b> {
    fn write_str(&mut self, mut s: &str) -> fmt::Result {
        while !s.is_empty() {
            let on_newline = self.on_newline;

            let split = match s.find('\n') {
                Some(pos) => {
                    self.on_newline = true;
                    pos + 1
                }
                None => {
                    self.on_newline = false;
                    s.len()
                }
            };

            let to_write = &s[..split];
            if on_newline && to_write != "\n" {
                self.fmt.write_str("    ")?;
            }
            self.fmt.write_str(to_write)?;

            s = &s[split..];
        }

        Ok(())
    }
}

impl<'de> Deserialize<'de> for Filtering {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FilteringVisitor;

        impl<'de> Visitor<'de> for FilteringVisitor {
            type Value = Filtering;

            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str("either only_tables or except_tables")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut only_tables = None;
                let mut except_tables = None;
                while let Some((key, value)) = map.next_entry()? {
                    match key {
                        "only_tables" => {
                            if only_tables.is_some() {
                                return Err(de::Error::duplicate_field("only_tables"));
                            }
                            only_tables = Some(value);
                        }
                        "except_tables" => {
                            if except_tables.is_some() {
                                return Err(de::Error::duplicate_field("except_tables"));
                            }
                            except_tables = Some(value);
                        }
                        _ => {
                            return Err(de::Error::unknown_field(
                                key,
                                &["only_tables", "except_tables"],
                            ))
                        }
                    }
                }
                match (only_tables, except_tables) {
                    (Some(_), Some(_)) => Err(de::Error::duplicate_field("except_tables")),
                    (Some(w), None) => Ok(Filtering::OnlyTables(w)),
                    (None, Some(b)) => Ok(Filtering::ExceptTables(b)),
                    (None, None) => Ok(Filtering::None),
                }
            }
        }

        deserializer.deserialize_map(FilteringVisitor)
    }
}
<commit_msg>Added helpful error message for print-schema when patch is not installed.<commit_after>use config;

use infer_schema_internals::*;
use serde::de::{self, MapAccess, Visitor};
use serde::{Deserialize, Deserializer};
use std::error::Error;
use std::fmt::{self, Display, Formatter, Write};
use std::fs::File;
use std::io::{self, Error as IoError, ErrorKind, Write as IoWrite};
use std::path::Path;
use std::process::Command;
use tempfile::NamedTempFile;

pub enum Filtering {
    OnlyTables(Vec<TableName>),
    ExceptTables(Vec<TableName>),
    None,
}

impl Default for Filtering {
    fn default() -> Self {
        Filtering::None
    }
}

impl Filtering {
    pub fn should_ignore_table(&self, name: &TableName) -> bool {
        use self::Filtering::*;

        match *self {
            OnlyTables(ref names) => !names.contains(name),
            ExceptTables(ref names) => names.contains(name),
            None => false,
        }
    }
}

pub fn run_print_schema<W: IoWrite>(
    database_url: &str,
    config: &config::PrintSchema,
    output: &mut W,
) -> Result<(), Box<dyn Error>> {
    let tempfile = NamedTempFile::new()?;
    let file = tempfile.reopen()?;
    output_schema(database_url, config, file, tempfile.path())?;

    // patch "replaces" our tempfile, meaning the old handle
    // does not include the patched output.
    let mut file = File::open(tempfile.path())?;
    io::copy(&mut file, output)?;
    Ok(())
}

fn simplify_patch_error(err: IoError) -> Box<dyn Error> {
    match err.kind() {
        ErrorKind::NotFound => "Unable to find `patch` command, is it installed?".into(),
        _ => err.into(),
    }
}

pub fn output_schema(
    database_url: &str,
    config: &config::PrintSchema,
    mut out: File,
    out_path: &Path,
) -> Result<(), Box<dyn Error>> {
    let table_names = load_table_names(database_url, config.schema_name())?
        .into_iter()
        .filter(|t| !config.filter.should_ignore_table(t))
        .collect::<Vec<_>>();
    let foreign_keys = load_foreign_key_constraints(database_url, config.schema_name())?;
    let foreign_keys =
        remove_unsafe_foreign_keys_for_codegen(database_url, &foreign_keys, &table_names);
    let table_data = table_names
        .into_iter()
        .map(|t| load_table_data(database_url, t))
        .collect::<Result<_, Box<dyn Error>>>()?;
    let definitions = TableDefinitions {
        tables: table_data,
        fk_constraints: foreign_keys,
        include_docs: config.with_docs,
        import_types: config.import_types(),
    };

    if let Some(schema_name) = config.schema_name() {
        write!(out, "{}", ModuleDefinition(schema_name, definitions))?;
    } else {
        write!(out, "{}", definitions)?;
    }

    if let Some(ref patch_file) = config.patch_file {
        let output = Command::new("patch")
            .arg(out_path)
            .arg(patch_file)
            .output()
            .map_err(simplify_patch_error)?;
        if !output.status.success() {
            let stdout = String::from_utf8_lossy(&output.stdout);
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(format!(
                "Failed to apply schema patch. stdout: {} stderr: {}",
                stdout, stderr,
            )
            .into());
        }
    }

    Ok(())
}

struct ModuleDefinition<'a>(&'a str, TableDefinitions<'a>);

impl<'a> Display for ModuleDefinition<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        {
            let mut out = PadAdapter::new(f);
            writeln!(out, "pub mod {} {{", self.0)?;
            write!(out, "{}", self.1)?;
        }
        writeln!(f, "}}")?;
        Ok(())
    }
}

struct TableDefinitions<'a> {
    tables: Vec<TableData>,
    fk_constraints: Vec<ForeignKeyConstraint>,
    include_docs: bool,
    import_types: Option<&'a [String]>,
}

impl<'a> Display for TableDefinitions<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let mut is_first = true;
        for table in &self.tables {
            if is_first {
                is_first = false;
            } else {
                writeln!(f)?;
            }
            writeln!(
                f,
                "{}",
                TableDefinition {
                    table,
                    include_docs: self.include_docs,
                    import_types: self.import_types,
                }
            )?;
        }

        if !self.fk_constraints.is_empty() {
            writeln!(f)?;
        }

        for foreign_key in &self.fk_constraints {
            writeln!(f, "{}", Joinable(foreign_key))?;
        }

        if self.tables.len() > 1 {
            write!(f, "\nallow_tables_to_appear_in_same_query!(")?;
            {
                let mut out = PadAdapter::new(f);
                writeln!(out)?;
                for table in &self.tables {
                    writeln!(out, "{},", table.name.name)?;
                }
            }
            writeln!(f, ");")?;
        }

        Ok(())
    }
}

struct TableDefinition<'a> {
    table: &'a TableData,
    import_types: Option<&'a [String]>,
    include_docs: bool,
}

impl<'a> Display for TableDefinition<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "table! {{")?;
        {
            let mut out = PadAdapter::new(f);
            writeln!(out)?;

            if let Some(types) = self.import_types {
                for import in types {
                    writeln!(out, "use {};", import)?;
                }
                writeln!(out)?;
            }

            if self.include_docs {
                for d in self.table.docs.lines() {
                    writeln!(out, "///{}{}", if d.is_empty() { "" } else { " " }, d)?;
                }
            }

            write!(out, "{} (", self.table.name)?;
            for (i, pk) in self.table.primary_key.iter().enumerate() {
                if i != 0 {
                    write!(out, ", ")?;
                }
                write!(out, "{}", pk)?;
            }

            write!(
                out,
                ") {}",
                ColumnDefinitions {
                    columns: &self.table.column_data,
                    include_docs: self.include_docs,
                }
            )?;
        }
        write!(f, "}}")?;
        Ok(())
    }
}

struct ColumnDefinitions<'a> {
    columns: &'a [ColumnDefinition],
    include_docs: bool,
}

impl<'a> Display for ColumnDefinitions<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        {
            let mut out = PadAdapter::new(f);
            writeln!(out, "{{")?;
            for column in self.columns {
                if self.include_docs {
                    for d in column.docs.lines() {
                        writeln!(out, "///{}{}", if d.is_empty() { "" } else { " " }, d)?;
                    }
                }
                if let Some(ref rust_name) = column.rust_name {
                    writeln!(out, r#"#[sql_name = "{}"]"#, column.sql_name)?;
                    writeln!(out, "{} -> {},", rust_name, column.ty)?;
                } else {
                    writeln!(out, "{} -> {},", column.sql_name, column.ty)?;
                }
            }
        }
        writeln!(f, "}}")?;
        Ok(())
    }
}

struct Joinable<'a>(&'a ForeignKeyConstraint);

impl<'a> Display for Joinable<'a> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(
            f,
            "joinable!({} -> {} ({}));",
            self.0.child_table.name, self.0.parent_table.name, self.0.foreign_key_rust_name,
        )
    }
}

/// Lifted directly from libcore/fmt/builders.rs
struct PadAdapter<'a, 'b: 'a> {
    fmt: &'a mut Formatter<'b>,
    on_newline: bool,
}

impl<'a, 'b: 'a> PadAdapter<'a, 'b> {
    fn new(fmt: &'a mut Formatter<'b>) -> PadAdapter<'a, 'b> {
        PadAdapter {
            fmt,
            on_newline: false,
        }
    }
}

impl<'a, 'b: 'a> Write for PadAdapter<'a, 'b> {
    fn write_str(&mut self, mut s: &str) -> fmt::Result {
        while !s.is_empty() {
            let on_newline = self.on_newline;

            let split = match s.find('\n') {
                Some(pos) => {
                    self.on_newline = true;
                    pos + 1
                }
                None => {
                    self.on_newline = false;
                    s.len()
                }
            };

            let to_write = &s[..split];
            if on_newline && to_write != "\n" {
                self.fmt.write_str("    ")?;
            }
            self.fmt.write_str(to_write)?;

            s = &s[split..];
        }

        Ok(())
    }
}

impl<'de> Deserialize<'de> for Filtering {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FilteringVisitor;

        impl<'de> Visitor<'de> for FilteringVisitor {
            type Value = Filtering;

            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str("either only_tables or except_tables")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut only_tables = None;
                let mut except_tables = None;
                while let Some((key, value)) = map.next_entry()? {
                    match key {
                        "only_tables" => {
                            if only_tables.is_some() {
                                return Err(de::Error::duplicate_field("only_tables"));
                            }
                            only_tables = Some(value);
                        }
                        "except_tables" => {
                            if except_tables.is_some() {
                                return Err(de::Error::duplicate_field("except_tables"));
                            }
                            except_tables = Some(value);
                        }
                        _ => {
                            return Err(de::Error::unknown_field(
                                key,
                                &["only_tables", "except_tables"],
                            ))
                        }
                    }
                }
                match (only_tables, except_tables) {
                    (Some(_), Some(_)) => Err(de::Error::duplicate_field("except_tables")),
                    (Some(w), None) => Ok(Filtering::OnlyTables(w)),
                    (None, Some(b)) => Ok(Filtering::ExceptTables(b)),
                    (None, None) => Ok(Filtering::None),
                }
            }
        }

        deserializer.deserialize_map(FilteringVisitor)
    }
}
<|endoftext|>


<commit_before>use bifrost::vector_clock::{VectorClock, StandardVectorClock, ServerVectorClock};
use bifrost::utils::time::get_time;
use chashmap::{CHashMap, WriteGuard};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use ram::types::{Id};
use ram::cell::{Cell, ReadError, WriteError};
use server::NebServer;
use futures::sync::mpsc::{Sender, Receiver, channel};
use super::*;

pub type TransactionGuard <'a> = WriteGuard<'a, TransactionId, Transaction>;

pub static DEFAULT_SERVICE_ID: u64 = hash_ident!(TNX_MANAGER_RPC_SERVICE) as u64;

#[derive(Debug, Serialize, Deserialize)]
pub enum TMError {
    TransactionNotFound,
    CannotLocateCellServer,
    NoResponseFromCellServer,
    AssertionError
}

#[derive(Clone)]
struct DataObject {
    server: u64,
    cell: Option<Cell>,
    new: bool
}

struct Transaction {
    start_time: i64, // use for timeout detecting
    id: TransactionId,
    data: BTreeMap<Id, DataObject>,
    writes: BTreeSet<Id>,
    await_chan: (Sender<()>, Receiver<()>)
}

service! {
    rpc begin() -> TransactionId;
    rpc read(tid: TransactionId, id: Id) -> TransactionExecResult<Cell, ReadError> | TMError;
    rpc write(tid: TransactionId, id: Id, cell: Cell) -> TransactionExecResult<(), WriteError> | TMError;
    rpc update(tid: TransactionId, cell: Cell) -> TransactionExecResult<(), WriteError> | TMError;
    rpc remove(tid: TransactionId, id: Id) -> TransactionExecResult<(), WriteError> | TMError;

    rpc prepare(tid: TransactionId) -> PrepareResult | TMError;
    rpc commit(tid: TransactionId);
    rpc abort(tid: TransactionId);

    rpc go_ahead(tid: BTreeSet<TransactionId>); // invoked by data site to continue on it's transaction in case of waiting
}

pub struct TransactionManager {
    server: Arc<NebServer>,
    transactions: CHashMap<TransactionId, Transaction>,
    data_sites: CHashMap<u64, Arc<data_site::AsyncServiceClient>>,
}
dispatch_rpc_service_functions!(TransactionManager);

impl TransactionManager {
    pub fn new(server: &Arc<NebServer>) -> Arc<TransactionManager> {
        Arc::new(TransactionManager {
            server: server.clone(),
            transactions: CHashMap::new(),
            data_sites: CHashMap::new()
        })
    }
}

impl TransactionManager {
    fn get_data_site(&self, server_id: u64) -> io::Result<Arc<data_site::AsyncServiceClient>> {
        if !self.data_sites.contains_key(&server_id) {
            let client = self.server.get_member_by_server_id(server_id)?;
            self.data_sites.upsert(server_id, || {
                data_site::AsyncServiceClient::new(DEFAULT_SERVICE_ID, &client)
            }, |_| {});
        }
        Ok(self.data_sites .get(&server_id).unwrap().clone())
    }
    fn get_data_site_by_id(&self, id: &Id) -> io::Result<(u64, Arc<data_site::AsyncServiceClient>)> {
        match self.server.get_server_id_by_id(id) {
            Some(id) => match self.get_data_site(id) {
                Ok(site) => Ok((id, site.clone())),
                Err(e) => Err(e)
            },
            _ => Err(io::Error::new(io::ErrorKind::NotFound, "cannot find data site for this id"))
        }
    }
    fn get_clock(&self) -> StandardVectorClock {
        self.server.tnx_peer.clock.to_clock()
    }
    fn merge_clock(&self, clock: &StandardVectorClock) {
        self.server.tnx_peer.clock.merge_with(clock)
    }
    fn get_transaction(&self, tid: &TransactionId) -> Result<TransactionGuard, TMError> {
        match self.transactions.get_mut(tid) {
            Some(tnx) => Ok(tnx),
            _ => {Err(TMError::TransactionNotFound)}
        }
    }
    fn changed_objs(&self, txn: TransactionGuard) -> BTreeMap<u64, Vec<(Id, DataObject)>> {
        let mut changed_objs: BTreeMap<u64, Vec<(Id, DataObject)>> = BTreeMap::new();
        for (id, data_obj) in &txn.data {
            changed_objs.entry(data_obj.server).or_insert_with(|| Vec::new()).push((*id, data_obj.clone()));
        }
        changed_objs
    }
}

impl Service for TransactionManager {
    fn begin(&self) -> Result<TransactionId, ()> {
        let id = self.server.tnx_peer.clock.inc();
        self.transactions.insert(id.clone(), Transaction {
            start_time: get_time(),
            id: id.clone(),
            data: BTreeMap::new(),
            writes: BTreeSet::new(),
            await_chan: channel(1)
        });
        Ok(id)
    }
    fn read(&self, tid: &TransactionId, id: &Id) -> Result<TransactionExecResult<Cell, ReadError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        if let Some(dataObj) = txn.data.get(id) {
            match dataObj.cell {
                Some(ref cell) => {
                    return Ok(TransactionExecResult::Accepted(cell.clone())) // read from cache
                },
                None => {
                   return Ok(TransactionExecResult::Error(ReadError::CellDoesNotExisted))
                }
            }
        }
        let server = self.get_data_site_by_id(&id);
        match server {
            Ok((server_id, server)) => {
                let self_server_id = self.server.server_id;
                let read_response = server.read(
                    &self_server_id,
                    &self.get_clock(),
                    tid, id
                ).wait();
                match read_response {
                    Ok(dsr) => {
                        let dsr = dsr.unwrap();
                        self.merge_clock(&dsr.clock);
                        match dsr.payload {
                            TransactionExecResult::Accepted(ref cell) => {
                                txn.data.insert(*id, DataObject {
                                    server: server_id,
                                    cell: Some(cell.clone()),
                                    new: false,
                                });
                            },
                            TransactionExecResult::Error(ReadError::CellDoesNotExisted) => {
                                txn.data.insert(*id, DataObject {
                                    server: server_id,
                                    cell: None,
                                    new: false,
                                });
                            }
                            TransactionExecResult::Wait => {} // TODO: deal with wait
                            _ => {}
                        }
                        Ok(dsr.payload)
                    },
                    Err(e) => {
                        error!("{:?}", e);
                        Err(TMError::NoResponseFromCellServer)
                    }
                }
            },
            Err(e) => {
                error!("{:?}", e);
                Err(TMError::CannotLocateCellServer)
            }
        }
    }
    fn write(&self, tid: &TransactionId, id: &Id, cell: &Cell) -> Result<TransactionExecResult<(), WriteError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        match self.server.get_server_id_by_id(id) {
            Some(server_id) => {
                let have_cached_cell = txn.data.contains_key(id);
                if !have_cached_cell {
                    txn.data.insert(*id, DataObject {
                        server: server_id,
                        cell: Some(cell.clone()),
                        new: true,
                    });
                    Ok(TransactionExecResult::Accepted(()))
                } else {
                    let mut data_obj = txn.data.get_mut(id).unwrap();
                    if !data_obj.cell.is_none() {
                        return Ok(TransactionExecResult::Error(WriteError::CellAlreadyExisted))
                    }
                    data_obj.cell = Some(cell.clone());
                    Ok(TransactionExecResult::Accepted(()))
                }
            },
            None => Err(TMError::CannotLocateCellServer)
        }
    }
    fn update(&self, tid: &TransactionId, cell: &Cell) -> Result<TransactionExecResult<(), WriteError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        let id = cell.id();
        match self.server.get_server_id_by_id(&id) {
            Some(server_id) => {
                let cell = cell.clone();
                if txn.data.contains_key(&id) {
                    txn.data.get_mut(&id).unwrap().cell = Some(cell)
                } else {
                    txn.data.insert(id, DataObject {
                        server: server_id,
                        cell: Some(cell),
                        new: false,
                    });
                }
                Ok(TransactionExecResult::Accepted(()))
            },
            None => Err(TMError::CannotLocateCellServer)
        }
    }
    fn remove(&self, tid: &TransactionId, id: &Id) -> Result<TransactionExecResult<(), WriteError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        match self.server.get_server_id_by_id(&id) {
            Some(server_id) => {
                if txn.data.contains_key(&id) {
                    let data_obj = txn.data.get_mut(&id).unwrap();
                    if data_obj.cell.is_none() {
                        return Ok(TransactionExecResult::Error(WriteError::CellDoesNotExisted))
                    }
                    data_obj.cell = None;
                } else {
                    txn.data.insert(*id, DataObject {
                        server: server_id,
                        cell: None,
                        new: false,
                    });
                }
                Ok(TransactionExecResult::Accepted(()))
            },
            None => Err(TMError::CannotLocateCellServer)
        }
    }
    fn prepare(&self, tid: &TransactionId) -> Result<PrepareResult, TMError> {
        let mut txn = self.get_transaction(tid)?;
        let mut changed_objs = self.changed_objs(txn);
        let data_sites: HashMap<u64, _> = changed_objs.iter().map(|(server_id, _)| {
            (*server_id, self.get_data_site(*server_id))
        }).collect();
        if data_sites.iter().any(|(_, data_site)| { data_site.is_err() }) {
            return Err(TMError::CannotLocateCellServer)
        }
        let data_sites: HashMap<u64, _> = data_sites.into_iter().map(
            |(server_id, data_site)| {
                (server_id, data_site.unwrap())
            }
        ).collect();
        let self_server_id = self.server.server_id;
        let prepare_futures: Vec<_> = changed_objs.iter().map(|(server, objs)| {
            let cell_ids: Vec<_> = objs.iter().map(|&(id, _)| id).collect();
            let data_site = data_sites.get(&server).unwrap();
            data_site.prepare(&self_server_id, &self.get_clock(), tid, &cell_ids)
        }).collect();
        let prepare_result = future::join_all(prepare_futures).wait();
        match prepare_result {
            Err(e) => {return Ok(PrepareResult::NetworkError);},
            Ok(responses) => {
                for prepare_res in responses {
                    if let Ok(prepare_res) = prepare_res {
                        self.merge_clock(&prepare_res.clock);
                        let payload = prepare_res.payload;
                        match payload {
                            PrepareResult::Success => {},
                            PrepareResult::Wait => {}, // TODO: deal with wait
                            _ => {
                                return Ok(payload) // something went wrong
                            }
                        }
                    } else {
                        return Err(TMError::AssertionError);
                    }
                }
            }
        }
        Err(TMError::CannotLocateCellServer)
    }
    fn commit(&self, tid: &TransactionId) -> Result<(), ()> {
        Err(())
    }
    fn abort(&self, tid: &TransactionId) -> Result<(), ()> {
        Err(())
    }
    fn go_ahead(&self, tid: &BTreeSet<TransactionId>) -> Result<(), ()> {
        Err(())
    }
}
<commit_msg>refactor txn manager data sites<commit_after>use bifrost::vector_clock::{VectorClock, StandardVectorClock, ServerVectorClock};
use bifrost::utils::time::get_time;
use chashmap::{CHashMap, WriteGuard};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use ram::types::{Id};
use ram::cell::{Cell, ReadError, WriteError};
use server::NebServer;
use futures::sync::mpsc::{Sender, Receiver, channel};
use super::*;

pub type TransactionGuard <'a> = WriteGuard<'a, TransactionId, Transaction>;

pub static DEFAULT_SERVICE_ID: u64 = hash_ident!(TNX_MANAGER_RPC_SERVICE) as u64;

#[derive(Debug, Serialize, Deserialize)]
pub enum TMError {
    TransactionNotFound,
    CannotLocateCellServer,
    NoResponseFromCellServer,
    AssertionError
}

#[derive(Clone)]
struct DataObject {
    server: u64,
    cell: Option<Cell>,
    new: bool
}

struct Transaction {
    start_time: i64, // use for timeout detecting
    id: TransactionId,
    data: BTreeMap<Id, DataObject>,
    writes: BTreeSet<Id>,
    await_chan: (Sender<()>, Receiver<()>)
}

service! {
    rpc begin() -> TransactionId;
    rpc read(tid: TransactionId, id: Id) -> TransactionExecResult<Cell, ReadError> | TMError;
    rpc write(tid: TransactionId, id: Id, cell: Cell) -> TransactionExecResult<(), WriteError> | TMError;
    rpc update(tid: TransactionId, cell: Cell) -> TransactionExecResult<(), WriteError> | TMError;
    rpc remove(tid: TransactionId, id: Id) -> TransactionExecResult<(), WriteError> | TMError;

    rpc prepare(tid: TransactionId) -> PrepareResult | TMError;
    rpc commit(tid: TransactionId);
    rpc abort(tid: TransactionId);

    rpc go_ahead(tid: BTreeSet<TransactionId>); // invoked by data site to continue on it's transaction in case of waiting
}

pub struct TransactionManager {
    server: Arc<NebServer>,
    transactions: CHashMap<TransactionId, Transaction>,
    data_sites: CHashMap<u64, Arc<data_site::AsyncServiceClient>>,
}
dispatch_rpc_service_functions!(TransactionManager);

impl TransactionManager {
    pub fn new(server: &Arc<NebServer>) -> Arc<TransactionManager> {
        Arc::new(TransactionManager {
            server: server.clone(),
            transactions: CHashMap::new(),
            data_sites: CHashMap::new()
        })
    }
}

impl TransactionManager {
    fn get_data_site(&self, server_id: u64) -> io::Result<Arc<data_site::AsyncServiceClient>> {
        if !self.data_sites.contains_key(&server_id) {
            let client = self.server.get_member_by_server_id(server_id)?;
            self.data_sites.upsert(server_id, || {
                data_site::AsyncServiceClient::new(DEFAULT_SERVICE_ID, &client)
            }, |_| {});
        }
        Ok(self.data_sites .get(&server_id).unwrap().clone())
    }
    fn get_data_site_by_id(&self, id: &Id) -> io::Result<(u64, Arc<data_site::AsyncServiceClient>)> {
        match self.server.get_server_id_by_id(id) {
            Some(id) => match self.get_data_site(id) {
                Ok(site) => Ok((id, site.clone())),
                Err(e) => Err(e)
            },
            _ => Err(io::Error::new(io::ErrorKind::NotFound, "cannot find data site for this id"))
        }
    }
    fn get_clock(&self) -> StandardVectorClock {
        self.server.tnx_peer.clock.to_clock()
    }
    fn merge_clock(&self, clock: &StandardVectorClock) {
        self.server.tnx_peer.clock.merge_with(clock)
    }
    fn get_transaction(&self, tid: &TransactionId) -> Result<TransactionGuard, TMError> {
        match self.transactions.get_mut(tid) {
            Some(tnx) => Ok(tnx),
            _ => {Err(TMError::TransactionNotFound)}
        }
    }
    fn changed_objs(&self, txn: &TransactionGuard) -> BTreeMap<u64, Vec<(Id, DataObject)>> {
        let mut changed_objs: BTreeMap<u64, Vec<(Id, DataObject)>> = BTreeMap::new();
        for (id, data_obj) in &txn.data {
            changed_objs.entry(data_obj.server).or_insert_with(|| Vec::new()).push((*id, data_obj.clone()));
        }
        changed_objs
    }
    fn data_sites(&self, changed_objs: &BTreeMap<u64, Vec<(Id, DataObject)>>)
        -> Result<HashMap<u64, Arc<data_site::AsyncServiceClient>>, TMError> {
        let data_sites: HashMap<u64, _> = changed_objs.iter().map(|(server_id, _)| {
            (*server_id, self.get_data_site(*server_id))
        }).collect();
        if data_sites.iter().any(|(_, data_site)| { data_site.is_err() }) {
            return Err(TMError::CannotLocateCellServer)
        }
        Ok(data_sites.into_iter().map(
            |(server_id, data_site)| {
                (server_id, data_site.unwrap())
            }
        ).collect())
    }
}

impl Service for TransactionManager {
    fn begin(&self) -> Result<TransactionId, ()> {
        let id = self.server.tnx_peer.clock.inc();
        self.transactions.insert(id.clone(), Transaction {
            start_time: get_time(),
            id: id.clone(),
            data: BTreeMap::new(),
            writes: BTreeSet::new(),
            await_chan: channel(1)
        });
        Ok(id)
    }
    fn read(&self, tid: &TransactionId, id: &Id) -> Result<TransactionExecResult<Cell, ReadError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        if let Some(dataObj) = txn.data.get(id) {
            match dataObj.cell {
                Some(ref cell) => {
                    return Ok(TransactionExecResult::Accepted(cell.clone())) // read from cache
                },
                None => {
                   return Ok(TransactionExecResult::Error(ReadError::CellDoesNotExisted))
                }
            }
        }
        let server = self.get_data_site_by_id(&id);
        match server {
            Ok((server_id, server)) => {
                let self_server_id = self.server.server_id;
                let read_response = server.read(
                    &self_server_id,
                    &self.get_clock(),
                    tid, id
                ).wait();
                match read_response {
                    Ok(dsr) => {
                        let dsr = dsr.unwrap();
                        self.merge_clock(&dsr.clock);
                        match dsr.payload {
                            TransactionExecResult::Accepted(ref cell) => {
                                txn.data.insert(*id, DataObject {
                                    server: server_id,
                                    cell: Some(cell.clone()),
                                    new: false,
                                });
                            },
                            TransactionExecResult::Error(ReadError::CellDoesNotExisted) => {
                                txn.data.insert(*id, DataObject {
                                    server: server_id,
                                    cell: None,
                                    new: false,
                                });
                            }
                            TransactionExecResult::Wait => {} // TODO: deal with wait
                            _ => {}
                        }
                        Ok(dsr.payload)
                    },
                    Err(e) => {
                        error!("{:?}", e);
                        Err(TMError::NoResponseFromCellServer)
                    }
                }
            },
            Err(e) => {
                error!("{:?}", e);
                Err(TMError::CannotLocateCellServer)
            }
        }
    }
    fn write(&self, tid: &TransactionId, id: &Id, cell: &Cell) -> Result<TransactionExecResult<(), WriteError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        match self.server.get_server_id_by_id(id) {
            Some(server_id) => {
                let have_cached_cell = txn.data.contains_key(id);
                if !have_cached_cell {
                    txn.data.insert(*id, DataObject {
                        server: server_id,
                        cell: Some(cell.clone()),
                        new: true,
                    });
                    Ok(TransactionExecResult::Accepted(()))
                } else {
                    let mut data_obj = txn.data.get_mut(id).unwrap();
                    if !data_obj.cell.is_none() {
                        return Ok(TransactionExecResult::Error(WriteError::CellAlreadyExisted))
                    }
                    data_obj.cell = Some(cell.clone());
                    Ok(TransactionExecResult::Accepted(()))
                }
            },
            None => Err(TMError::CannotLocateCellServer)
        }
    }
    fn update(&self, tid: &TransactionId, cell: &Cell) -> Result<TransactionExecResult<(), WriteError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        let id = cell.id();
        match self.server.get_server_id_by_id(&id) {
            Some(server_id) => {
                let cell = cell.clone();
                if txn.data.contains_key(&id) {
                    txn.data.get_mut(&id).unwrap().cell = Some(cell)
                } else {
                    txn.data.insert(id, DataObject {
                        server: server_id,
                        cell: Some(cell),
                        new: false,
                    });
                }
                Ok(TransactionExecResult::Accepted(()))
            },
            None => Err(TMError::CannotLocateCellServer)
        }
    }
    fn remove(&self, tid: &TransactionId, id: &Id) -> Result<TransactionExecResult<(), WriteError>, TMError> {
        let mut txn = self.get_transaction(tid)?;
        match self.server.get_server_id_by_id(&id) {
            Some(server_id) => {
                if txn.data.contains_key(&id) {
                    let data_obj = txn.data.get_mut(&id).unwrap();
                    if data_obj.cell.is_none() {
                        return Ok(TransactionExecResult::Error(WriteError::CellDoesNotExisted))
                    }
                    data_obj.cell = None;
                } else {
                    txn.data.insert(*id, DataObject {
                        server: server_id,
                        cell: None,
                        new: false,
                    });
                }
                Ok(TransactionExecResult::Accepted(()))
            },
            None => Err(TMError::CannotLocateCellServer)
        }
    }
    fn prepare(&self, tid: &TransactionId) -> Result<PrepareResult, TMError> {
        let mut txn = self.get_transaction(tid)?;
        let mut changed_objs = self.changed_objs(&txn);
        let data_sites = self.data_sites(&changed_objs)?;
        let self_server_id = self.server.server_id;
        let prepare_futures: Vec<_> = changed_objs.iter().map(|(server, objs)| {
            let cell_ids: Vec<_> = objs.iter().map(|&(id, _)| id).collect();
            let data_site = data_sites.get(&server).unwrap();
            data_site.prepare(&self_server_id, &self.get_clock(), tid, &cell_ids)
        }).collect();
        let prepare_result = future::join_all(prepare_futures).wait();
        match prepare_result {
            Err(e) => {return Ok(PrepareResult::NetworkError);},
            Ok(responses) => {
                for prepare_res in responses {
                    if let Ok(prepare_res) = prepare_res {
                        self.merge_clock(&prepare_res.clock);
                        let payload = prepare_res.payload;
                        match payload {
                            PrepareResult::Success => {},
                            PrepareResult::Wait => {}, // TODO: deal with wait
                            _ => {
                                return Ok(payload) // something went wrong
                            }
                        }
                    } else {
                        return Err(TMError::AssertionError);
                    }
                }
            }
        }
        Err(TMError::CannotLocateCellServer)
    }
    fn commit(&self, tid: &TransactionId) -> Result<(), ()> {
        Err(())
    }
    fn abort(&self, tid: &TransactionId) -> Result<(), ()> {
        Err(())
    }
    fn go_ahead(&self, tid: &BTreeSet<TransactionId>) -> Result<(), ()> {
        Err(())
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

pub struct JsType {
    uid: Uuid,
    t: Box<JsT>,
}

impl JsType {
    fn new(t: Box<JsT>) -> JsType {
        JsType {
            uid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsType {
    fn eq(&self, other: &Self) -> bool {
        self.uid == other.uid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsType{}

impl Hash for JsType {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uid.hash(state);
        }
    }
}

pub trait JsT {}
<commit_msg>Rename JsType to JsT, JsT to JsTrait<commit_after>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

pub trait JsTrait {}

pub struct JsT {
    uid: Uuid,
    t: Box<JsTrait>,
}

impl JsT {
    pub fn new(t: Box<JsTrait>) -> JsT {
        JsT {
            uid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsT {
    fn eq(&self, other: &Self) -> bool {
        self.uid == other.uid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsT {}

impl Hash for JsT {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uid.hash(state);
        }
    }
}

<|endoftext|>


<commit_before>extern crate entity_rust;

use std::collections::HashMap;

use entity_rust::events;

#[test]
fn event_queue_accessors() {
	let i : i64 = 5;
	let name = String::from("my_queue");
	events::event_queue_push(&name, i);
	let queue = events::event_queue_get(&name);
	assert!(queue.len() == 1);
	assert!(i == queue[0]);
}

#[test]
fn test_how_string_works_as_hashmap_index() {
	let name = String::from("my_queue");
	let mut m : HashMap<String, i64> = HashMap::new();
	let i = 543;
	m.insert(name.clone(), i);
	let j = *m.get(&name.clone()).unwrap();
	assert!(i == j);
}

/*
#[test]
fn events_example_trigger() {
	let arg = events::example::Argument { x: 1, y: 2};
	events::example::trigger(arg);
	let existed = events::event_queue_apply(events::example::EventUUID, |queue| {
		assert!(queue.len() == 1);
		assert!(arg == queue[0])
	});
	if !existed {
		assert!(false)
	}
}
*/<commit_msg>test if queue modification works<commit_after>extern crate entity_rust;

use std::collections::HashMap;

use entity_rust::events;

#[test]
#[ignore] // pending reset (tests pollute eachother now)
fn event_queue_initial_set() {
	let i : i64 = 5;
	let name = String::from("my_queue");
	events::event_queue_push(&name, i);
	let queue = events::event_queue_get(&name);
	assert!(queue.len() == 1);
	assert!(i == queue[0]);
}

#[test]
fn event_queue_multi_set() {
	let i : i64 = 5;
	let j : i64 = 352;
	let k : i64 = 234;
	let name = String::from("my_queue");
	events::event_queue_push(&name, i);
	events::event_queue_push(&name, j);
	events::event_queue_push(&name, k);
	let queue = events::event_queue_get(&name);
	assert!(queue.len() == 3);
	assert!(i == queue[0]);
	assert!(j == queue[1]);
	assert!(k == queue[2]);
}

#[test]
fn test_how_string_works_as_hashmap_index() {
	let name = String::from("my_queue");
	let mut m : HashMap<String, i64> = HashMap::new();
	let i = 543;
	m.insert(name.clone(), i);
	let j = *m.get(&name.clone()).unwrap();
	assert!(i == j);
}

/*
#[test]
fn events_example_trigger() {
	let arg = events::example::Argument { x: 1, y: 2};
	events::example::trigger(arg);
	let existed = events::event_queue_apply(events::example::EventUUID, |queue| {
		assert!(queue.len() == 1);
		assert!(arg == queue[0])
	});
	if !existed {
		assert!(false)
	}
}
*/<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(macro_rules)]

extern crate string_telephone;
extern crate collections;

pub mod test_client;
<commit_msg>Removed unneeded test lib - each file is run, apparently<commit_after><|endoftext|>


<commit_before>#![warn(rust_2018_idioms)] // while we're getting used to 2018
#![allow(clippy::all)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::redundant_clone)]

use cargo::core::shell::Shell;
use cargo::util::toml::StringOrVec;
use cargo::util::CliError;
use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
use cargo_util::{ProcessBuilder, ProcessError};
use std::collections::BTreeMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};

mod cli;
mod commands;

use crate::command_prelude::*;

fn main() {
    #[cfg(feature = "pretty-env-logger")]
    pretty_env_logger::init_custom_env("CARGO_LOG");
    #[cfg(not(feature = "pretty-env-logger"))]
    env_logger::init_from_env("CARGO_LOG");

    let mut config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = match cargo::ops::fix_maybe_exec_rustc(&config) {
        Ok(true) => Ok(()),
        Ok(false) => {
            let _token = cargo::util::job::setup();
            cli::main(&mut config)
        }
        Err(e) => Err(CliError::from(e)),
    };

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

/// Table for defining the aliases which come builtin in `Cargo`.
/// The contents are structured as: `(alias, aliased_command, description)`.
const BUILTIN_ALIASES: [(&str, &str, &str); 5] = [
    ("b", "build", "alias: build"),
    ("c", "check", "alias: check"),
    ("d", "doc", "alias: doc"),
    ("r", "run", "alias: run"),
    ("t", "test", "alias: test"),
];

/// Function which contains the list of all of the builtin aliases and it's
/// corresponding execs represented as &str.
fn builtin_aliases_execs(cmd: &str) -> Option<&(&str, &str, &str)> {
    BUILTIN_ALIASES.iter().find(|alias| alias.0 == cmd)
}

fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let user_alias = match config.get_string(&alias_name) {
        Ok(Some(record)) => Some(
            record
                .val
                .split_whitespace()
                .map(|s| s.to_string())
                .collect(),
        ),
        Ok(None) => None,
        Err(_) => config.get::<Option<Vec<String>>>(&alias_name)?,
    };

    let result = user_alias.or_else(|| {
        builtin_aliases_execs(command).map(|command_str| vec![command_str.1.to_string()])
    });
    Ok(result)
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeMap<String, CommandInfo> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeMap::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(
                    filename[prefix.len()..end].to_string(),
                    CommandInfo::External { path: path.clone() },
                );
            }
        }
    }

    for cmd in commands::builtin() {
        commands.insert(
            cmd.get_name().to_string(),
            CommandInfo::BuiltIn {
                about: cmd.get_about().map(|s| s.to_string()),
            },
        );
    }

    // Add the builtin_aliases and them descriptions to the
    // `commands` `BTreeMap`.
    for command in &BUILTIN_ALIASES {
        commands.insert(
            command.0.to_string(),
            CommandInfo::BuiltIn {
                about: Some(command.2.to_string()),
            },
        );
    }

    // Add the user-defined aliases
    if let Ok(aliases) = config.get::<BTreeMap<String, StringOrVec>>("alias") {
        for (name, target) in aliases.iter() {
            commands.insert(
                name.to_string(),
                CommandInfo::Alias {
                    target: target.clone(),
                },
            );
        }
    }

    commands
}

fn find_external_subcommand(config: &Config, cmd: &str) -> Option<PathBuf> {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file))
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
    let path = find_external_subcommand(config, cmd);
    let command = match path {
        Some(command) => command,
        None => {
            let suggestions = list_commands(config);
            let did_you_mean = closest_msg(cmd, suggestions.keys(), |c| c);
            let err = anyhow::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean);
            return Err(CliError::new(err, 101));
        }
    };

    let cargo_exe = config.cargo_exe()?;
    let err = match ProcessBuilder::new(&command)
        .env(cargo::CARGO_ENV, cargo_exe)
        .args(args)
        .exec_replace()
    {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let Some(perr) = err.downcast_ref::<ProcessError>() {
        if let Some(code) = perr.code {
            return Err(CliError::code(code));
        }
    }
    Err(CliError::new(err, 101))
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    path.as_ref().is_file()
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if any HTTP options are specified,
    // such as proxies or custom certificate authorities. The custom
    // transport, however, is not as well battle-tested.

    match cargo::ops::needs_custom_http_transport(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<commit_msg>Include `help` in `--list`<commit_after>#![warn(rust_2018_idioms)] // while we're getting used to 2018
#![allow(clippy::all)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::redundant_clone)]

use cargo::core::shell::Shell;
use cargo::util::toml::StringOrVec;
use cargo::util::CliError;
use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
use cargo_util::{ProcessBuilder, ProcessError};
use std::collections::BTreeMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};

mod cli;
mod commands;

use crate::command_prelude::*;

fn main() {
    #[cfg(feature = "pretty-env-logger")]
    pretty_env_logger::init_custom_env("CARGO_LOG");
    #[cfg(not(feature = "pretty-env-logger"))]
    env_logger::init_from_env("CARGO_LOG");

    let mut config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = match cargo::ops::fix_maybe_exec_rustc(&config) {
        Ok(true) => Ok(()),
        Ok(false) => {
            let _token = cargo::util::job::setup();
            cli::main(&mut config)
        }
        Err(e) => Err(CliError::from(e)),
    };

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

/// Table for defining the aliases which come builtin in `Cargo`.
/// The contents are structured as: `(alias, aliased_command, description)`.
const BUILTIN_ALIASES: [(&str, &str, &str); 5] = [
    ("b", "build", "alias: build"),
    ("c", "check", "alias: check"),
    ("d", "doc", "alias: doc"),
    ("r", "run", "alias: run"),
    ("t", "test", "alias: test"),
];

/// Function which contains the list of all of the builtin aliases and it's
/// corresponding execs represented as &str.
fn builtin_aliases_execs(cmd: &str) -> Option<&(&str, &str, &str)> {
    BUILTIN_ALIASES.iter().find(|alias| alias.0 == cmd)
}

fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let user_alias = match config.get_string(&alias_name) {
        Ok(Some(record)) => Some(
            record
                .val
                .split_whitespace()
                .map(|s| s.to_string())
                .collect(),
        ),
        Ok(None) => None,
        Err(_) => config.get::<Option<Vec<String>>>(&alias_name)?,
    };

    let result = user_alias.or_else(|| {
        builtin_aliases_execs(command).map(|command_str| vec![command_str.1.to_string()])
    });
    Ok(result)
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeMap<String, CommandInfo> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeMap::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(
                    filename[prefix.len()..end].to_string(),
                    CommandInfo::External { path: path.clone() },
                );
            }
        }
    }

    for cmd in commands::builtin() {
        commands.insert(
            cmd.get_name().to_string(),
            CommandInfo::BuiltIn {
                about: cmd.get_about().map(|s| s.to_string()),
            },
        );
    }

    // Add the builtin_aliases and them descriptions to the
    // `commands` `BTreeMap`.
    for command in &BUILTIN_ALIASES {
        commands.insert(
            command.0.to_string(),
            CommandInfo::BuiltIn {
                about: Some(command.2.to_string()),
            },
        );
    }

    // Add the user-defined aliases
    if let Ok(aliases) = config.get::<BTreeMap<String, StringOrVec>>("alias") {
        for (name, target) in aliases.iter() {
            commands.insert(
                name.to_string(),
                CommandInfo::Alias {
                    target: target.clone(),
                },
            );
        }
    }

    // `help` is special, so it needs to be inserted separately.
    commands.insert(
        "help".to_string(),
        CommandInfo::BuiltIn {
            about: Some("Displays help for a cargo subcommand".to_string()),
        },
    );

    commands
}

fn find_external_subcommand(config: &Config, cmd: &str) -> Option<PathBuf> {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file))
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
    let path = find_external_subcommand(config, cmd);
    let command = match path {
        Some(command) => command,
        None => {
            let suggestions = list_commands(config);
            let did_you_mean = closest_msg(cmd, suggestions.keys(), |c| c);
            let err = anyhow::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean);
            return Err(CliError::new(err, 101));
        }
    };

    let cargo_exe = config.cargo_exe()?;
    let err = match ProcessBuilder::new(&command)
        .env(cargo::CARGO_ENV, cargo_exe)
        .args(args)
        .exec_replace()
    {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let Some(perr) = err.downcast_ref::<ProcessError>() {
        if let Some(code) = perr.code {
            return Err(CliError::code(code));
        }
    }
    Err(CliError::new(err, 101))
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    path.as_ref().is_file()
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if any HTTP options are specified,
    // such as proxies or custom certificate authorities. The custom
    // transport, however, is not as well battle-tested.

    match cargo::ops::needs_custom_http_transport(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<|endoftext|>