<commit_before>//! Modules common to all targets.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

pub mod memory;
pub mod startup;
pub mod builtins;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Added routines for spinning on registers to check they've settled. You need to do this with the LM4F120 run-time clock gating registers.<commit_after>//! Modules common to all targets.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

pub mod memory;
pub mod startup;
pub mod builtins;
pub mod volatile;

use core::intrinsics::{volatile_store, volatile_load};
use core::ops::{BitOrAssign, BitAndAssign, Not};

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Performs a volatile_store on the ptr, then repeatedly reads *ptr until it
/// equals the given value. Useful for writing to Run-time Clock Gating
/// Control registers on a Tiva-C/LM4F120.
pub unsafe fn write_settle<T: PartialEq + Copy>(ptr: *mut T, value: T) {
    volatile_store(ptr, value);
    // Wait for value to settle
    while volatile_load(ptr) != value {
       asm!("NOP");
    }
}

/// Performs a read modify write on the ptr, then repeatedly reads *ptr until
/// it equals the given value. Useful for writing to Run-time Clock Gating
/// Control registers on a Tiva-C/LM4F120.
pub unsafe fn read_set_write_settle<T: PartialEq + Copy + BitOrAssign>(ptr: *mut T, set_bits: T) {
    let mut t:T = volatile_load(ptr);
    t |= set_bits;
    write_settle(ptr, t);
}

/// Performs a read modify write on the ptr, then repeatedly reads *ptr until
/// it equals the given value. Useful for writing to Run-time Clock Gating
/// Control registers on a Tiva-C/LM4F120. ANDs the ! of clear_bits.
pub unsafe fn read_clear_write_settle<T: PartialEq + Copy + BitAndAssign + Not<Output=T>>(ptr: *mut T, clear_bits: T) {
    let mut t:T = volatile_load(ptr);
    t &= !clear_bits;
    write_settle(ptr, t);
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>use clap::{App, Arg};
use lucet_idl::{run, Config, IDLError};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::PathBuf;

#[derive(Default, Clone, Debug)]
pub struct ExeConfig {
    pub input_path: PathBuf,
    pub output_path: Option<PathBuf>,
    pub config: Config,
}

impl ExeConfig {
    pub fn parse() -> Result<Self, IDLError> {
        let matches = App::new("lucet-idl")
            .version("1.0")
            .about("lucet_idl code generator")
            .arg(
                Arg::with_name("input_file")
                    .short("i")
                    .long("input")
                    .takes_value(true)
                    .required(true)
                    .help("Path to the input file"),
            )
            .arg(
                Arg::with_name("target")
                    .short("t")
                    .long("target")
                    .default_value("Generic")
                    .takes_value(true)
                    .required(false)
                    .help("Target, one of: x86, x86_64, x86_64_32, generic"),
            )
            .arg(
                Arg::with_name("backend")
                    .short("b")
                    .long("backend")
                    .default_value("c")
                    .takes_value(true)
                    .required(false)
                    .help("Backend, one of: c, rust"),
            )
            .arg(
                Arg::with_name("zero-native-pointers")
                    .short("z")
                    .long("zero-native-pointers")
                    .takes_value(false)
                    .required(false)
                    .help("Do not serialize native pointers"),
            )
            .get_matches();
        let input_path = PathBuf::from(
            matches
                .value_of("input_file")
                .ok_or(IDLError::UsageError("Input file required"))?,
        );
        let config = Config::parse(
            matches.value_of("target").unwrap(),
            matches.value_of("backend").unwrap(),
            matches.is_present("zero-native-pointers"),
        );
        Ok(ExeConfig {
            input_path,
            output_path: None,
            config,
        })
    }
}
fn doit() -> Result<(), IDLError> {
    let exe_config = ExeConfig::parse()?;
    let mut source = String::new();
    File::open(&exe_config.input_path)?.read_to_string(&mut source)?;

    run(&exe_config.config, &source, Box::new(io::stdout()))?;

    Ok(())
}

fn main() {
    doit().unwrap();
}
<commit_msg>lucet-idl: input file isnt a named argument<commit_after>use clap::{App, Arg};
use lucet_idl::{run, Config, IDLError};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::PathBuf;

#[derive(Default, Clone, Debug)]
pub struct ExeConfig {
    pub input_path: PathBuf,
    pub output_path: Option<PathBuf>,
    pub config: Config,
}

impl ExeConfig {
    pub fn parse() -> Result<Self, IDLError> {
        let matches = App::new("lucet-idl")
            .version("1.0")
            .about("lucet_idl code generator")
            .arg(
                Arg::with_name("input")
                    .required(true)
                    .help("Path to the input file"),
            )
            .arg(
                Arg::with_name("target")
                    .short("t")
                    .long("target")
                    .default_value("Generic")
                    .takes_value(true)
                    .required(false)
                    .help("Target, one of: x86, x86_64, x86_64_32, generic"),
            )
            .arg(
                Arg::with_name("backend")
                    .short("b")
                    .long("backend")
                    .default_value("c")
                    .takes_value(true)
                    .required(false)
                    .help("Backend, one of: c, rust"),
            )
            .arg(
                Arg::with_name("zero-native-pointers")
                    .short("z")
                    .long("zero-native-pointers")
                    .takes_value(false)
                    .required(false)
                    .help("Do not serialize native pointers"),
            )
            .get_matches();
        let input_path = PathBuf::from(
            matches
                .value_of("input")
                .ok_or(IDLError::UsageError("Input file required"))?,
        );
        let config = Config::parse(
            matches.value_of("target").unwrap(),
            matches.value_of("backend").unwrap(),
            matches.is_present("zero-native-pointers"),
        );
        Ok(ExeConfig {
            input_path,
            output_path: None,
            config,
        })
    }
}
fn doit() -> Result<(), IDLError> {
    let exe_config = ExeConfig::parse()?;
    let mut source = String::new();
    File::open(&exe_config.input_path)?.read_to_string(&mut source)?;

    run(&exe_config.config, &source, Box::new(io::stdout()))?;

    Ok(())
}

fn main() {
    doit().unwrap();
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use admission_control_proto::proto::admission_control_grpc::{
    create_admission_control, AdmissionControlClient,
};
use admission_control_service::admission_control_service::AdmissionControlService;
use config::config::{NetworkConfig, NodeConfig, RoleType};
use consensus::consensus_provider::{make_consensus_provider, ConsensusProvider};
use crypto::ed25519::*;
use debug_interface::{node_debug_service::NodeDebugService, proto::node_debug_interface_grpc};
use execution_proto::proto::execution_grpc;
use execution_service::ExecutionService;
use futures::future::{FutureExt, TryFutureExt};
use grpc_helpers::ServerHandle;
use grpcio::{ChannelBuilder, EnvBuilder, ServerBuilder};
use grpcio_sys;
use logger::prelude::*;
use mempool::{proto::mempool_grpc::MempoolClient, MempoolRuntime};
use metrics::metric_server;
use network::{
    validator_network::{
        network_builder::{NetworkBuilder, TransportType},
        LibraNetworkProvider, CONSENSUS_DIRECT_SEND_PROTOCOL, CONSENSUS_RPC_PROTOCOL,
        MEMPOOL_DIRECT_SEND_PROTOCOL, STATE_SYNCHRONIZER_MSG_PROTOCOL,
    },
    NetworkPublicKeys, ProtocolId,
};
use state_synchronizer::StateSynchronizer;
use std::{
    cmp::min,
    convert::{TryFrom, TryInto},
    sync::Arc,
    thread,
    time::Instant,
};
use storage_client::{StorageRead, StorageReadServiceClient, StorageWriteServiceClient};
use storage_service::start_storage_service;
use tokio::runtime::{Builder, Runtime};
use types::account_address::AccountAddress as PeerId;
use vm_validator::vm_validator::VMValidator;

pub struct LibraHandle {
    _ac: ServerHandle,
    _mempool: Option<MempoolRuntime>,
    _state_synchronizer: StateSynchronizer,
    _network: Runtime,
    consensus: Option<Box<dyn ConsensusProvider>>,
    _execution: ServerHandle,
    _storage: ServerHandle,
    _debug: ServerHandle,
}

impl Drop for LibraHandle {
    fn drop(&mut self) {
        if let Some(consensus) = &mut self.consensus {
            consensus.stop();
        }
    }
}

fn setup_ac(config: &NodeConfig) -> (::grpcio::Server, AdmissionControlClient) {
    let env = Arc::new(
        EnvBuilder::new()
            .name_prefix("grpc-ac-")
            .cq_count(unsafe { min(grpcio_sys::gpr_cpu_num_cores() as usize * 2, 32) })
            .build(),
    );
    let port = config.admission_control.admission_control_service_port;

    // Create mempool client
    let mempool_client = match (&config.network.role).into() {
        RoleType::FullNode => None,
        RoleType::Validator => {
            let connection_str = format!("localhost:{}", config.mempool.mempool_service_port);
            let env2 = Arc::new(EnvBuilder::new().name_prefix("grpc-ac-mem-").build());
            Some(Arc::new(MempoolClient::new(
                ChannelBuilder::new(env2).connect(&connection_str),
            )))
        }
    };

    // Create storage read client
    let storage_client: Arc<dyn StorageRead> = Arc::new(StorageReadServiceClient::new(
        Arc::new(EnvBuilder::new().name_prefix("grpc-ac-sto-").build()),
        "localhost",
        config.storage.port,
    ));

    let vm_validator = Arc::new(VMValidator::new(&config, Arc::clone(&storage_client)));

    let handle = AdmissionControlService::new(
        mempool_client,
        storage_client,
        vm_validator,
        config
            .admission_control
            .need_to_check_mempool_before_validation,
    );
    let service = create_admission_control(handle);
    let server = ServerBuilder::new(Arc::clone(&env))
        .register_service(service)
        .bind(config.admission_control.address.clone(), port)
        .build()
        .expect("Unable to create grpc server");

    let connection_str = format!("localhost:{}", port);
    let client = AdmissionControlClient::new(ChannelBuilder::new(env).connect(&connection_str));
    (server, client)
}

fn setup_executor(config: &NodeConfig) -> ::grpcio::Server {
    let client_env = Arc::new(EnvBuilder::new().name_prefix("grpc-exe-sto-").build());
    let storage_read_client = Arc::new(StorageReadServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
    ));
    let storage_write_client = Arc::new(StorageWriteServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
        config.storage.grpc_max_receive_len,
    ));

    let handle = ExecutionService::new(storage_read_client, storage_write_client, config);
    let service = execution_grpc::create_execution(handle);
    ::grpcio::ServerBuilder::new(Arc::new(EnvBuilder::new().name_prefix("grpc-exe-").build()))
        .register_service(service)
        .bind(config.execution.address.clone(), config.execution.port)
        .build()
        .expect("Unable to create grpc server")
}

fn setup_debug_interface(config: &NodeConfig) -> ::grpcio::Server {
    let env = Arc::new(EnvBuilder::new().name_prefix("grpc-debug-").build());
    // Start Debug interface
    let debug_service =
        node_debug_interface_grpc::create_node_debug_interface(NodeDebugService::new());
    ::grpcio::ServerBuilder::new(env)
        .register_service(debug_service)
        .bind(
            config.debug_interface.address.clone(),
            config.debug_interface.admission_control_node_debug_port,
        )
        .build()
        .expect("Unable to create grpc server")
}

pub fn setup_network(
    peer_id: PeerId,
    config: &mut NetworkConfig,
) -> (Runtime, Box<dyn LibraNetworkProvider>) {
    let runtime = Builder::new()
        .name_prefix("network-")
        .build()
        .expect("Failed to start runtime. Won't be able to start networking.");
    let role: RoleType = (&config.role).into();
    let trusted_peers = config
        .trusted_peers
        .get_trusted_network_peers()
        .clone()
        .into_iter()
        .map(|(peer_id, (signing_public_key, identity_public_key))| {
            (
                peer_id,
                NetworkPublicKeys {
                    signing_public_key,
                    identity_public_key,
                },
            )
        })
        .collect();
    let seed_peers = config
        .seed_peers
        .seed_peers
        .clone()
        .into_iter()
        .map(|(peer_id, addrs)| (peer_id.try_into().expect("Invalid PeerId"), addrs))
        .collect();
    let network_signing_private = config.peer_keypairs.take_network_signing_private()
        .expect("Failed to move network signing private key out of NodeConfig, key not set or moved already");
    let network_signing_public: Ed25519PublicKey = (&network_signing_private).into();
    let listen_addr = config.listen_address.clone();
    let advertised_addr = config.advertised_address.clone();
    let mut network_builder = NetworkBuilder::new(runtime.executor(), peer_id, listen_addr, role);
    if config.enable_encryption_and_authentication {
        network_builder
            .transport(TransportType::TcpNoise)
            .identity_keys(config.peer_keypairs.get_network_identity_keypair());
    } else {
        network_builder.transport(TransportType::Tcp);
    };
    let (_listen_addr, network_provider) = network_builder
        .advertised_address(advertised_addr)
        .seed_peers(seed_peers)
        .trusted_peers(trusted_peers)
        .signing_keys((network_signing_private, network_signing_public))
        .discovery_interval_ms(config.discovery_interval_ms)
        .connectivity_check_interval_ms(config.connectivity_check_interval_ms)
        .direct_send_protocols(vec![
            ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(STATE_SYNCHRONIZER_MSG_PROTOCOL),
        ])
        .rpc_protocols(vec![ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL)])
        .build();
    (runtime, network_provider)
}

pub fn setup_environment(node_config: &mut NodeConfig) -> (AdmissionControlClient, LibraHandle) {
    crash_handler::setup_panic_handler();

    let mut instant = Instant::now();
    let storage = start_storage_service(&node_config);
    debug!(
        "Storage service started in {} ms",
        instant.elapsed().as_millis()
    );

    instant = Instant::now();
    let execution = ServerHandle::setup(setup_executor(&node_config));
    debug!(
        "Execution service started in {} ms",
        instant.elapsed().as_millis()
    );

    instant = Instant::now();
    let (ac_server, ac_client) = setup_ac(&node_config);
    let ac = ServerHandle::setup(ac_server);
    debug!("AC started in {} ms", instant.elapsed().as_millis());

    instant = Instant::now();
    let peer_id = PeerId::try_from(node_config.network.peer_id.clone()).expect("Invalid PeerId");
    let (runtime, mut network_provider) = setup_network(peer_id, &mut node_config.network);
    debug!("Network started in {} ms", instant.elapsed().as_millis());

    let (state_sync_network_sender, state_sync_network_events) = network_provider
        .add_state_synchronizer(vec![ProtocolId::from_static(
            STATE_SYNCHRONIZER_MSG_PROTOCOL,
        )]);

    let state_synchronizer = StateSynchronizer::bootstrap(
        vec![(state_sync_network_sender, state_sync_network_events)],
        &node_config,
        vec![], // TODO: pass in empty vector for now, will be derived from node config later
    );

    let mut mempool = None;
    let mut consensus = None;
    if let RoleType::Validator = (&node_config.network.role).into() {
        instant = Instant::now();
        let (mempool_network_sender, mempool_network_events) = network_provider
            .add_mempool(vec![ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL)]);
        mempool = Some(MempoolRuntime::bootstrap(
            &node_config,
            mempool_network_sender,
            mempool_network_events,
        ));
        debug!("Mempool started in {} ms", instant.elapsed().as_millis());

        instant = Instant::now();
        let (consensus_network_sender, consensus_network_events) =
            network_provider.add_consensus(vec![
                ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL),
                ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ]);
        let mut consensus_provider = make_consensus_provider(
            node_config,
            consensus_network_sender,
            consensus_network_events,
            state_synchronizer.create_client(),
        );
        consensus_provider
            .start()
            .expect("Failed to start consensus. Can't proceed.");
        consensus = Some(consensus_provider);
        debug!("Consensus started in {} ms", instant.elapsed().as_millis());
    }

    // Start the network providers.
    runtime
        .executor()
        .spawn(network_provider.start().unit_error().compat());

    let debug_if = ServerHandle::setup(setup_debug_interface(&node_config));

    let metrics_port = node_config.debug_interface.metrics_server_port;
    let metric_host = node_config.debug_interface.address.clone();
    thread::spawn(move || metric_server::start_server((metric_host.as_str(), metrics_port)));

    let libra_handle = LibraHandle {
        _ac: ac,
        _mempool: mempool,
        _state_synchronizer: state_synchronizer,
        _network: runtime,
        consensus,
        _execution: execution,
        _storage: storage,
        _debug: debug_if,
    };
    (ac_client, libra_handle)
}
<commit_msg>[libra node] Initialize network module after consensus<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use admission_control_proto::proto::admission_control_grpc::{
    create_admission_control, AdmissionControlClient,
};
use admission_control_service::admission_control_service::AdmissionControlService;
use config::config::{NetworkConfig, NodeConfig, RoleType};
use consensus::consensus_provider::{make_consensus_provider, ConsensusProvider};
use crypto::ed25519::*;
use debug_interface::{node_debug_service::NodeDebugService, proto::node_debug_interface_grpc};
use execution_proto::proto::execution_grpc;
use execution_service::ExecutionService;
use futures::future::{FutureExt, TryFutureExt};
use grpc_helpers::ServerHandle;
use grpcio::{ChannelBuilder, EnvBuilder, ServerBuilder};
use grpcio_sys;
use logger::prelude::*;
use mempool::{proto::mempool_grpc::MempoolClient, MempoolRuntime};
use metrics::metric_server;
use network::{
    validator_network::{
        network_builder::{NetworkBuilder, TransportType},
        LibraNetworkProvider, CONSENSUS_DIRECT_SEND_PROTOCOL, CONSENSUS_RPC_PROTOCOL,
        MEMPOOL_DIRECT_SEND_PROTOCOL, STATE_SYNCHRONIZER_MSG_PROTOCOL,
    },
    NetworkPublicKeys, ProtocolId,
};
use state_synchronizer::StateSynchronizer;
use std::{
    cmp::min,
    convert::{TryFrom, TryInto},
    sync::Arc,
    thread,
    time::Instant,
};
use storage_client::{StorageRead, StorageReadServiceClient, StorageWriteServiceClient};
use storage_service::start_storage_service;
use tokio::runtime::{Builder, Runtime};
use types::account_address::AccountAddress as PeerId;
use vm_validator::vm_validator::VMValidator;

pub struct LibraHandle {
    _ac: ServerHandle,
    _mempool: Option<MempoolRuntime>,
    _state_synchronizer: StateSynchronizer,
    _network: Runtime,
    consensus: Option<Box<dyn ConsensusProvider>>,
    _execution: ServerHandle,
    _storage: ServerHandle,
    _debug: ServerHandle,
}

impl Drop for LibraHandle {
    fn drop(&mut self) {
        if let Some(consensus) = &mut self.consensus {
            consensus.stop();
        }
    }
}

fn setup_ac(config: &NodeConfig) -> (::grpcio::Server, AdmissionControlClient) {
    let env = Arc::new(
        EnvBuilder::new()
            .name_prefix("grpc-ac-")
            .cq_count(unsafe { min(grpcio_sys::gpr_cpu_num_cores() as usize * 2, 32) })
            .build(),
    );
    let port = config.admission_control.admission_control_service_port;

    // Create mempool client
    let mempool_client = match (&config.network.role).into() {
        RoleType::FullNode => None,
        RoleType::Validator => {
            let connection_str = format!("localhost:{}", config.mempool.mempool_service_port);
            let env2 = Arc::new(EnvBuilder::new().name_prefix("grpc-ac-mem-").build());
            Some(Arc::new(MempoolClient::new(
                ChannelBuilder::new(env2).connect(&connection_str),
            )))
        }
    };

    // Create storage read client
    let storage_client: Arc<dyn StorageRead> = Arc::new(StorageReadServiceClient::new(
        Arc::new(EnvBuilder::new().name_prefix("grpc-ac-sto-").build()),
        "localhost",
        config.storage.port,
    ));

    let vm_validator = Arc::new(VMValidator::new(&config, Arc::clone(&storage_client)));

    let handle = AdmissionControlService::new(
        mempool_client,
        storage_client,
        vm_validator,
        config
            .admission_control
            .need_to_check_mempool_before_validation,
    );
    let service = create_admission_control(handle);
    let server = ServerBuilder::new(Arc::clone(&env))
        .register_service(service)
        .bind(config.admission_control.address.clone(), port)
        .build()
        .expect("Unable to create grpc server");

    let connection_str = format!("localhost:{}", port);
    let client = AdmissionControlClient::new(ChannelBuilder::new(env).connect(&connection_str));
    (server, client)
}

fn setup_executor(config: &NodeConfig) -> ::grpcio::Server {
    let client_env = Arc::new(EnvBuilder::new().name_prefix("grpc-exe-sto-").build());
    let storage_read_client = Arc::new(StorageReadServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
    ));
    let storage_write_client = Arc::new(StorageWriteServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
        config.storage.grpc_max_receive_len,
    ));

    let handle = ExecutionService::new(storage_read_client, storage_write_client, config);
    let service = execution_grpc::create_execution(handle);
    ::grpcio::ServerBuilder::new(Arc::new(EnvBuilder::new().name_prefix("grpc-exe-").build()))
        .register_service(service)
        .bind(config.execution.address.clone(), config.execution.port)
        .build()
        .expect("Unable to create grpc server")
}

fn setup_debug_interface(config: &NodeConfig) -> ::grpcio::Server {
    let env = Arc::new(EnvBuilder::new().name_prefix("grpc-debug-").build());
    // Start Debug interface
    let debug_service =
        node_debug_interface_grpc::create_node_debug_interface(NodeDebugService::new());
    ::grpcio::ServerBuilder::new(env)
        .register_service(debug_service)
        .bind(
            config.debug_interface.address.clone(),
            config.debug_interface.admission_control_node_debug_port,
        )
        .build()
        .expect("Unable to create grpc server")
}

pub fn setup_network(
    peer_id: PeerId,
    config: &mut NetworkConfig,
) -> (Runtime, Box<dyn LibraNetworkProvider>) {
    let runtime = Builder::new()
        .name_prefix("network-")
        .build()
        .expect("Failed to start runtime. Won't be able to start networking.");
    let role: RoleType = (&config.role).into();
    let trusted_peers = config
        .trusted_peers
        .get_trusted_network_peers()
        .clone()
        .into_iter()
        .map(|(peer_id, (signing_public_key, identity_public_key))| {
            (
                peer_id,
                NetworkPublicKeys {
                    signing_public_key,
                    identity_public_key,
                },
            )
        })
        .collect();
    let seed_peers = config
        .seed_peers
        .seed_peers
        .clone()
        .into_iter()
        .map(|(peer_id, addrs)| (peer_id.try_into().expect("Invalid PeerId"), addrs))
        .collect();
    let network_signing_private = config.peer_keypairs.take_network_signing_private()
        .expect("Failed to move network signing private key out of NodeConfig, key not set or moved already");
    let network_signing_public: Ed25519PublicKey = (&network_signing_private).into();
    let listen_addr = config.listen_address.clone();
    let advertised_addr = config.advertised_address.clone();
    let mut network_builder = NetworkBuilder::new(runtime.executor(), peer_id, listen_addr, role);
    if config.enable_encryption_and_authentication {
        network_builder
            .transport(TransportType::TcpNoise)
            .identity_keys(config.peer_keypairs.get_network_identity_keypair());
    } else {
        network_builder.transport(TransportType::Tcp);
    };
    let (_listen_addr, network_provider) = network_builder
        .advertised_address(advertised_addr)
        .seed_peers(seed_peers)
        .trusted_peers(trusted_peers)
        .signing_keys((network_signing_private, network_signing_public))
        .discovery_interval_ms(config.discovery_interval_ms)
        .connectivity_check_interval_ms(config.connectivity_check_interval_ms)
        .direct_send_protocols(vec![
            ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(STATE_SYNCHRONIZER_MSG_PROTOCOL),
        ])
        .rpc_protocols(vec![ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL)])
        .build();
    (runtime, network_provider)
}

pub fn setup_environment(node_config: &mut NodeConfig) -> (AdmissionControlClient, LibraHandle) {
    crash_handler::setup_panic_handler();

    let mut instant = Instant::now();
    let storage = start_storage_service(&node_config);
    debug!(
        "Storage service started in {} ms",
        instant.elapsed().as_millis()
    );

    instant = Instant::now();
    let execution = ServerHandle::setup(setup_executor(&node_config));
    debug!(
        "Execution service started in {} ms",
        instant.elapsed().as_millis()
    );

    instant = Instant::now();
    let (ac_server, ac_client) = setup_ac(&node_config);
    let ac = ServerHandle::setup(ac_server);
    debug!("AC started in {} ms", instant.elapsed().as_millis());

    instant = Instant::now();
    let peer_id = PeerId::try_from(node_config.network.peer_id.clone()).expect("Invalid PeerId");
    let (runtime, mut network_provider) = setup_network(peer_id, &mut node_config.network);
    debug!("Network started in {} ms", instant.elapsed().as_millis());

    let (state_sync_network_sender, state_sync_network_events) = network_provider
        .add_state_synchronizer(vec![ProtocolId::from_static(
            STATE_SYNCHRONIZER_MSG_PROTOCOL,
        )]);

    let state_synchronizer = StateSynchronizer::bootstrap(
        vec![(state_sync_network_sender, state_sync_network_events)],
        &node_config,
        vec![], // TODO: pass in empty vector for now, will be derived from node config later
    );

    let mut mempool = None;
    let mut consensus = None;
    if let RoleType::Validator = (&node_config.network.role).into() {
        // Initialize and start mempool.
        instant = Instant::now();
        let (mempool_network_sender, mempool_network_events) = network_provider
            .add_mempool(vec![ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL)]);
        mempool = Some(MempoolRuntime::bootstrap(
            &node_config,
            mempool_network_sender,
            mempool_network_events,
        ));
        debug!("Mempool started in {} ms", instant.elapsed().as_millis());

        // Start the network provider.
        // Note: We need to start network provider before consensus, because the consensus
        // initialization is blocked on state synchronizer to sync to the initial root ledger info,
        // which in turn cannot make progress before network initialization because the NewPeer
        // events which state synchronizer uses to know its peers are delivered by network provider.
        // If we were to start network provider after consensus, we create a cyclic dependency from
        // network provider -> consensus -> state synchronizer -> network provier. This deadlock was
        // observed in GitHub Issue #749. A long term fix might be make consensus initialization
        // async instead of blocking on state synchronizer.
        let (consensus_network_sender, consensus_network_events) =
            network_provider.add_consensus(vec![
                ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL),
                ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ]);
        runtime
            .executor()
            .spawn(network_provider.start().unit_error().compat());

        // Initialize and start consensus.
        instant = Instant::now();
        let mut consensus_provider = make_consensus_provider(
            node_config,
            consensus_network_sender,
            consensus_network_events,
            state_synchronizer.create_client(),
        );
        consensus_provider
            .start()
            .expect("Failed to start consensus. Can't proceed.");
        consensus = Some(consensus_provider);
        debug!("Consensus started in {} ms", instant.elapsed().as_millis());
    } else {
        // Start the network provider.
        runtime
            .executor()
            .spawn(network_provider.start().unit_error().compat());
    }

    let debug_if = ServerHandle::setup(setup_debug_interface(&node_config));

    let metrics_port = node_config.debug_interface.metrics_server_port;
    let metric_host = node_config.debug_interface.address.clone();
    thread::spawn(move || metric_server::start_server((metric_host.as_str(), metrics_port)));

    let libra_handle = LibraHandle {
        _ac: ac,
        _mempool: mempool,
        _state_synchronizer: state_synchronizer,
        _network: runtime,
        consensus,
        _execution: execution,
        _storage: storage,
        _debug: debug_if,
    };
    (ac_client, libra_handle)
}
<|endoftext|>


<commit_before><commit_msg>Make time and duration copy types<commit_after><|endoftext|>


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

use jsapi::{JSObject, JSString};

use std::cast;
use std::libc::c_void;

static JSVAL_TAG_SHIFT: int = 47;

#[repr(u8)]
enum ValueType {
    JSVAL_TYPE_DOUBLE              = 0x00,
    JSVAL_TYPE_INT32               = 0x01,
    JSVAL_TYPE_UNDEFINED           = 0x02,
    JSVAL_TYPE_BOOLEAN             = 0x03,
    JSVAL_TYPE_MAGIC               = 0x04,
    JSVAL_TYPE_STRING              = 0x05,
    JSVAL_TYPE_NULL                = 0x06,
    JSVAL_TYPE_OBJECT              = 0x07,

    /* These never appear in a jsval; they are only provided as an out-of-band value. */
    JSVAL_TYPE_UNKNOWN             = 0x20,
    JSVAL_TYPE_MISSING             = 0x21
}

static JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32;

#[repr(u32)]
enum ValueTag {
    JSVAL_TAG_DOUBLE               = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_DOUBLE as u32),
    JSVAL_TAG_INT32                = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_INT32 as u32),
    JSVAL_TAG_UNDEFINED            = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_UNDEFINED as u32),
    JSVAL_TAG_STRING               = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_STRING as u32),
    JSVAL_TAG_BOOLEAN              = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_BOOLEAN as u32),
    JSVAL_TAG_MAGIC                = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_MAGIC as u32),
    JSVAL_TAG_NULL                 = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_NULL as u32),
    JSVAL_TAG_OBJECT               = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_OBJECT as u32),
}

#[repr(u64)]
enum ValueShiftedTag {
    JSVAL_SHIFTED_TAG_MAX_DOUBLE   = (((JSVAL_TAG_MAX_DOUBLE as u64) << JSVAL_TAG_SHIFT) | 0xFFFFFFFFu64),
    JSVAL_SHIFTED_TAG_INT32        = ((JSVAL_TAG_INT32 as u64)      << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_UNDEFINED    = ((JSVAL_TAG_UNDEFINED as u64)  << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_STRING       = ((JSVAL_TAG_STRING as u64)     << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_BOOLEAN      = ((JSVAL_TAG_BOOLEAN as u64)    << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_MAGIC        = ((JSVAL_TAG_MAGIC as u64)      << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_NULL         = ((JSVAL_TAG_NULL as u64)       << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_OBJECT       = ((JSVAL_TAG_OBJECT as u64)     << JSVAL_TAG_SHIFT)
}

static JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF;

// JSVal was originally type of u64.
// now this become {u64} because of the union abi issue on ARM arch. See #398.
#[deriving(Eq,Clone)]
pub struct JSVal {
    v: u64
}

#[inline(always)]
fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal {
    JSVal {
        v: ((tag as u32 as u64) << JSVAL_TAG_SHIFT) | payload
    }
}

#[inline(always)]
pub fn NullValue() -> JSVal {
    BuildJSVal(JSVAL_TAG_NULL, 0)
}

#[inline(always)]
pub fn UndefinedValue() -> JSVal {
    BuildJSVal(JSVAL_TAG_UNDEFINED, 0)
}

#[inline(always)]
pub fn Int32Value(i: i32) -> JSVal {
    BuildJSVal(JSVAL_TAG_INT32, i as u64)
}

#[inline(always)]
pub fn DoubleValue(f: f64) -> JSVal {
    let bits: u64 = unsafe { cast::transmute(f) };
    assert!(bits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE as u64)
    JSVal {
        v: bits
    }
}

#[inline(always)]
pub fn UInt32Value(ui: u32) -> JSVal {
    if ui > 0x7fffffff {
        DoubleValue(ui as f64)
    } else {
        Int32Value(ui as i32)
    }
}

#[inline(always)]
pub fn StringValue(s: &JSString) -> JSVal {
    let bits = s as *JSString as uint as u64;
    assert!((bits >> JSVAL_TAG_SHIFT) == 0);
    BuildJSVal(JSVAL_TAG_STRING, bits)
}

#[inline(always)]
pub fn BooleanValue(b: bool) -> JSVal {
    BuildJSVal(JSVAL_TAG_BOOLEAN, b as u64)
}

#[inline(always)]
pub fn ObjectValue(o: &JSObject) -> JSVal {
    let bits = o as *JSObject as uint as u64;
    assert!((bits >> JSVAL_TAG_SHIFT) == 0);
    BuildJSVal(JSVAL_TAG_OBJECT, bits)
}

#[inline(always)]
pub fn ObjectOrNullValue(o: *JSObject) -> JSVal {
    if o.is_null() {
        NullValue()
    } else {
        ObjectValue(unsafe { &*o })
    }
}

#[inline(always)]
pub fn PrivateValue(o: *c_void) -> JSVal {
    let ptrBits = o as uint as u64;
    assert!((ptrBits & 1) == 0);
    JSVal {
        v: ptrBits >> 1
    }
}

impl JSVal {
    pub fn is_undefined(&self) -> bool {
        self.v == JSVAL_SHIFTED_TAG_UNDEFINED as u64
    }

    pub fn is_null(&self) -> bool {
        self.v == JSVAL_SHIFTED_TAG_NULL as u64
    }

    pub fn is_null_or_undefined(&self) -> bool {
        self.is_null() || self.is_undefined()
    }

    pub fn is_double(&self) -> bool {
        self.v <= JSVAL_SHIFTED_TAG_MAX_DOUBLE as u64
    }

    pub fn is_primitive(&self) -> bool {
        static JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = JSVAL_SHIFTED_TAG_OBJECT as u64;
        self.v < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET
    }

    pub fn is_object(&self) -> bool {
        assert!((self.v >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT as u64);
        self.v >= JSVAL_SHIFTED_TAG_OBJECT as u64
    }

    pub fn to_object(&self) -> *JSObject {
        assert!(self.is_object());
        self.to_object_or_null()
    }

    pub fn is_object_or_null(&self) -> bool {
        static JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET: u64 = JSVAL_SHIFTED_TAG_NULL as u64;
        assert!((self.v >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT as u64);
        self.v >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET
    }

    pub fn to_object_or_null(&self) -> *JSObject {
        assert!(self.is_object_or_null());
        let ptrBits = self.v & JSVAL_PAYLOAD_MASK;
        assert!((ptrBits & 0x7) == 0);
        ptrBits as uint as *JSObject
    }

    pub fn to_private(&self) -> *c_void {
        assert!(self.is_double());
        assert!((self.v & 0x8000000000000000u64) == 0);
        (self.v << 1) as uint as *c_void
    }
}
<commit_msg>In Int32Value, cast to u32 before casting to u64.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

use jsapi::{JSObject, JSString};

use std::cast;
use std::libc::c_void;

static JSVAL_TAG_SHIFT: int = 47;

#[repr(u8)]
enum ValueType {
    JSVAL_TYPE_DOUBLE              = 0x00,
    JSVAL_TYPE_INT32               = 0x01,
    JSVAL_TYPE_UNDEFINED           = 0x02,
    JSVAL_TYPE_BOOLEAN             = 0x03,
    JSVAL_TYPE_MAGIC               = 0x04,
    JSVAL_TYPE_STRING              = 0x05,
    JSVAL_TYPE_NULL                = 0x06,
    JSVAL_TYPE_OBJECT              = 0x07,

    /* These never appear in a jsval; they are only provided as an out-of-band value. */
    JSVAL_TYPE_UNKNOWN             = 0x20,
    JSVAL_TYPE_MISSING             = 0x21
}

static JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32;

#[repr(u32)]
enum ValueTag {
    JSVAL_TAG_DOUBLE               = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_DOUBLE as u32),
    JSVAL_TAG_INT32                = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_INT32 as u32),
    JSVAL_TAG_UNDEFINED            = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_UNDEFINED as u32),
    JSVAL_TAG_STRING               = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_STRING as u32),
    JSVAL_TAG_BOOLEAN              = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_BOOLEAN as u32),
    JSVAL_TAG_MAGIC                = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_MAGIC as u32),
    JSVAL_TAG_NULL                 = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_NULL as u32),
    JSVAL_TAG_OBJECT               = JSVAL_TAG_MAX_DOUBLE | (JSVAL_TYPE_OBJECT as u32),
}

#[repr(u64)]
enum ValueShiftedTag {
    JSVAL_SHIFTED_TAG_MAX_DOUBLE   = (((JSVAL_TAG_MAX_DOUBLE as u64) << JSVAL_TAG_SHIFT) | 0xFFFFFFFFu64),
    JSVAL_SHIFTED_TAG_INT32        = ((JSVAL_TAG_INT32 as u64)      << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_UNDEFINED    = ((JSVAL_TAG_UNDEFINED as u64)  << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_STRING       = ((JSVAL_TAG_STRING as u64)     << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_BOOLEAN      = ((JSVAL_TAG_BOOLEAN as u64)    << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_MAGIC        = ((JSVAL_TAG_MAGIC as u64)      << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_NULL         = ((JSVAL_TAG_NULL as u64)       << JSVAL_TAG_SHIFT),
    JSVAL_SHIFTED_TAG_OBJECT       = ((JSVAL_TAG_OBJECT as u64)     << JSVAL_TAG_SHIFT)
}

static JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF;

// JSVal was originally type of u64.
// now this become {u64} because of the union abi issue on ARM arch. See #398.
#[deriving(Eq,Clone)]
pub struct JSVal {
    v: u64
}

#[inline(always)]
fn BuildJSVal(tag: ValueTag, payload: u64) -> JSVal {
    JSVal {
        v: ((tag as u32 as u64) << JSVAL_TAG_SHIFT) | payload
    }
}

#[inline(always)]
pub fn NullValue() -> JSVal {
    BuildJSVal(JSVAL_TAG_NULL, 0)
}

#[inline(always)]
pub fn UndefinedValue() -> JSVal {
    BuildJSVal(JSVAL_TAG_UNDEFINED, 0)
}

#[inline(always)]
pub fn Int32Value(i: i32) -> JSVal {
    BuildJSVal(JSVAL_TAG_INT32, i as u32 as u64)
}

#[inline(always)]
pub fn DoubleValue(f: f64) -> JSVal {
    let bits: u64 = unsafe { cast::transmute(f) };
    assert!(bits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE as u64)
    JSVal {
        v: bits
    }
}

#[inline(always)]
pub fn UInt32Value(ui: u32) -> JSVal {
    if ui > 0x7fffffff {
        DoubleValue(ui as f64)
    } else {
        Int32Value(ui as i32)
    }
}

#[inline(always)]
pub fn StringValue(s: &JSString) -> JSVal {
    let bits = s as *JSString as uint as u64;
    assert!((bits >> JSVAL_TAG_SHIFT) == 0);
    BuildJSVal(JSVAL_TAG_STRING, bits)
}

#[inline(always)]
pub fn BooleanValue(b: bool) -> JSVal {
    BuildJSVal(JSVAL_TAG_BOOLEAN, b as u64)
}

#[inline(always)]
pub fn ObjectValue(o: &JSObject) -> JSVal {
    let bits = o as *JSObject as uint as u64;
    assert!((bits >> JSVAL_TAG_SHIFT) == 0);
    BuildJSVal(JSVAL_TAG_OBJECT, bits)
}

#[inline(always)]
pub fn ObjectOrNullValue(o: *JSObject) -> JSVal {
    if o.is_null() {
        NullValue()
    } else {
        ObjectValue(unsafe { &*o })
    }
}

#[inline(always)]
pub fn PrivateValue(o: *c_void) -> JSVal {
    let ptrBits = o as uint as u64;
    assert!((ptrBits & 1) == 0);
    JSVal {
        v: ptrBits >> 1
    }
}

impl JSVal {
    pub fn is_undefined(&self) -> bool {
        self.v == JSVAL_SHIFTED_TAG_UNDEFINED as u64
    }

    pub fn is_null(&self) -> bool {
        self.v == JSVAL_SHIFTED_TAG_NULL as u64
    }

    pub fn is_null_or_undefined(&self) -> bool {
        self.is_null() || self.is_undefined()
    }

    pub fn is_double(&self) -> bool {
        self.v <= JSVAL_SHIFTED_TAG_MAX_DOUBLE as u64
    }

    pub fn is_primitive(&self) -> bool {
        static JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = JSVAL_SHIFTED_TAG_OBJECT as u64;
        self.v < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET
    }

    pub fn is_object(&self) -> bool {
        assert!((self.v >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT as u64);
        self.v >= JSVAL_SHIFTED_TAG_OBJECT as u64
    }

    pub fn to_object(&self) -> *JSObject {
        assert!(self.is_object());
        self.to_object_or_null()
    }

    pub fn is_object_or_null(&self) -> bool {
        static JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET: u64 = JSVAL_SHIFTED_TAG_NULL as u64;
        assert!((self.v >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT as u64);
        self.v >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET
    }

    pub fn to_object_or_null(&self) -> *JSObject {
        assert!(self.is_object_or_null());
        let ptrBits = self.v & JSVAL_PAYLOAD_MASK;
        assert!((ptrBits & 0x7) == 0);
        ptrBits as uint as *JSObject
    }

    pub fn to_private(&self) -> *c_void {
        assert!(self.is_double());
        assert!((self.v & 0x8000000000000000u64) == 0);
        (self.v << 1) as uint as *c_void
    }
}
<|endoftext|>


<commit_before>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
#[macro_use] extern crate serde_json;
extern crate serde_yaml;
#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgsTag {
    Args,
    Rets,
}

#[derive(Serialize, Deserialize, Debug)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs = HashMap<String, ArgValue>;
type NamedArgs2 = HashMap<String, serde_json::value::Value>;

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize, Debug)]
struct ClientRequest {
    #[serde(rename = "type")]
    tp: DbusMessageType,
    name: String,
    args: Option<NamedArgs2>,
}

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, NamedArgs);

type CRequest = HashMap<String, ClientRequestBody>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest { tp: DbusMessageType::Method, name: "api_name".to_string(),
                            args: Some([    ("param1".to_string(), json!("Hi")),
                                            ("param2".to_string(), json!(true)),
                                            ("param3".to_string(), json!(17i64)),
                                            ("param4".to_string(), json!(2.718281828f64)),
                                       ].iter().cloned().collect())
                          };
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let d: ClientRequest = serde_json::from_str(&rs).expect("json deserialization error");
    println!("d: {:?}", d);

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name".to_string(), rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

}
<commit_msg>played with manual json serialization.<commit_after>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
#[macro_use] extern crate serde_json;
extern crate serde_yaml;
#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

impl ArgValue {
    fn to_json(&self, n: &str) -> String {
        match *self {
            ArgValue::None             =>   "".to_string(),
            ArgValue::Str(ref v)       =>   format!("\"{}\":{}", n, v ),
            ArgValue::Bool(ref v)      =>   format!("\"{}\":{}", n, v ),
            ArgValue::Byte(ref v)      =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int16(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int32(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::Int64(ref v)     =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt16(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt32(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::UInt64(ref v)    =>   format!("\"{}\":{}", n, v ),
            ArgValue::Double(ref v)    =>   format!("\"{}\":{}", n, v ),
        }
    }
}

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgsTag {
    Args,
    Rets,
}

#[derive(Serialize, Deserialize, Debug)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs = HashMap<String, ArgValue>;
type NamedArgs2 = HashMap<String, serde_json::value::Value>;

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize, Debug)]
struct ClientRequest {
    #[serde(rename = "type")]
    tp: DbusMessageType,
    name: String,
    args: Option<NamedArgs2>,
    rets: Option<NamedArgs2>,
}

impl ClientRequest {
    fn to_json(&self) -> String {
        fn serialize_args_or_rets(tag: &str, ar: &Option<NamedArgs2>) -> String {
            match ar {
                &Some(ref a) => {
                    let args_serialized: Vec<_> = a.iter().map( |ret| {
                        let (n, val) = ret;
                        //val.to_json(n)
                        format!("\"{}\":{}", n, val)
                        } ).collect();
                    format!("\"{}\": {{ {}", tag, args_serialized.join(","))
                },
                &None =>  "".to_string(),
            }
        }
        let json_reply_prefix = format!("{{\"type\":\"{:?}\",\"name\":\"{}\",", &self.tp, &self.name);
        let args_serialized = serialize_args_or_rets("args", &self.args);
        let rets_serialized = serialize_args_or_rets("rets", &self.rets);
        format!("{}{}{} }} }}",json_reply_prefix, args_serialized, rets_serialized).to_string()
    }
}

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, NamedArgs);

type CRequest = HashMap<String, ClientRequestBody>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest { tp: DbusMessageType::Method, name: "api_name".to_string(),
                            args: Some([    ("param1".to_string(), json!("Hi")),
                                            ("param2".to_string(), json!(true)),
                                            ("param3".to_string(), json!(17i64)),
                                            ("param4".to_string(), json!(2.718281828f64)),
                                       ].iter().cloned().collect()),
                            rets: None,
                          };
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let d: ClientRequest = serde_json::from_str(&rs).expect("json deserialization error");
    println!("d: {:?}", d);

    let data = "{\"type\":\"Method\",\"name\":\"utest_4p2r\",\"rets\":{\"parm1\":71,\"parm2\":12.12 } }";
    let d2: ClientRequest = serde_json::from_str(&data).expect("json deserialization error");
    println!("d2: {:?}", d2);
    println!("d2.to_json(): {}", d2.to_json());

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name".to_string(), rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

}
<|endoftext|>


<commit_before>use std::net::{UdpSocket, SocketAddr, Ipv4Addr, SocketAddrV4};
use std::time;
use tracker::{Announce, Result, ResultExt, Response, TrackerResponse, Event, Error, ErrorKind, dns};
use std::collections::HashMap;
use {CONFIG, PEER_ID, amy};
use std::sync::Arc;
use std::io::{self, Write, Read, Cursor};
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use slog::Logger;
use url::Url;
use rand::random;

// We're not going to bother with backoff, if the tracker/network aren't working now
// the torrent can just resend a request later.
const TIMEOUT_MS: u64 = 5000;
const RETRANS_MS: u64 = 500;

pub struct Handler {
    id: usize,
    sock: UdpSocket,
    connections: HashMap<usize, Connection>,
    transactions: HashMap<u32, usize>,
    conn_count: usize,
    l: Logger,
    buf: Vec<u8>,
}

struct Connection {
    torrent: usize,
    last_updated: time::Instant,
    last_retrans: time::Instant,
    state: State,
    announce: Announce,
}

enum State {
    ResolvingDNS { port: u16 },
    Connecting { addr: SocketAddr, data: [u8; 16] },
    Announcing { addr: SocketAddr, data: [u8; 98] },
}

impl Handler {
    pub fn new(reg: &Arc<amy::Registrar>, l: Logger) -> io::Result<Handler> {
        let port = CONFIG.port;
        let sock = UdpSocket::bind(("0.0.0.0", port))?;
        sock.set_nonblocking(true)?;
        let id = reg.register(&sock, amy::Event::Read)?;
        Ok(Handler {
            id,
            sock,
            connections: HashMap::new(),
            transactions: HashMap::new(),
            l,
            conn_count: 0,
            buf: vec![0u8; 350],
        })
    }

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

    pub fn complete(&self) -> bool {
        self.connections.is_empty()
    }

    pub fn contains(&self, id: usize) -> bool {
        self.connections.contains_key(&id)
    }

    pub fn new_announce(&mut self, req: Announce, url: &Url, dns: &mut dns::Resolver) -> Result<()> {
        debug!(self.l, "Received a new announce req for {:?}", url);
        let host = url.host_str().ok_or::<Error>(
            ErrorKind::InvalidRequest(format!("Tracker announce url has no host!")).into()
        )?;
        let port = url.port().ok_or::<Error>(
            ErrorKind::InvalidRequest(format!("Tracker announce url has no port!")).into()
        )?;

        let id = self.new_conn();
        self.connections.insert(id, Connection {
            torrent: req.id,
            last_updated: time::Instant::now(),
            last_retrans: time::Instant::now(),
            state: State::ResolvingDNS { port },
            announce: req,
        });
        debug!(self.l, "Dispatching DNS req for {:?}, url: {:?}", id, host);
        dns.new_query(id, host);
        Ok(())
    }

    pub fn dns_resolved(&mut self, resp: dns::QueryResponse) -> Option<Response> {
        let id = resp.id;
        let mut success = false;
        debug!(self.l, "Received a DNS resp for {:?}", id);
        let resp = if let Some(mut conn) = self.connections.get_mut(&id) {
            match conn.state {
                State::ResolvingDNS { port } => {
                    conn.last_updated = time::Instant::now();
                    let tid = random::<u32>();
                    let mut data = [0u8; 16];
                    {
                        let mut connect_req = Cursor::new(&mut data[..]);
                        connect_req.write_u64::<BigEndian>(0x41727101980).unwrap();
                        connect_req.write_u32::<BigEndian>(0).unwrap();
                        connect_req.write_u32::<BigEndian>(tid).unwrap();
                    }
                    match resp.res {
                        Ok(ip) => {
                            success = true;
                            conn.state = State::Connecting { addr: SocketAddr::new(ip, port), data };
                            self.transactions.insert(tid, id);
                            None
                        }
                        Err(e) => Some((conn.torrent, Err(e))),
                    }
                }
                _ => None,
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
            resp
        } else if success {
            self.send_data(id)
        } else {
            None
        }
    }

    pub fn readable(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        loop {
            match self.sock.recv_from(&mut self.buf[..]) {
                Ok((v, _)) => {
                    let action = (&self.buf[0..4]).read_u32::<BigEndian>().unwrap();
                    match action {
                        0 if v == 16 => {
                            if let Some(r) = self.process_connect() {
                                resps.push(r);
                            }
                        }
                        1 if v >= 20 => {
                            if let Some(r) = self.process_announce(v) {
                                resps.push(r);
                            }
                        }
                        3 if v >= 8 => {
                            if let Some(r) = self.process_error(v) {
                                resps.push(r);
                            }
                        }
                        _ => { debug!(self.l, "Received invalid response from tracker!") }
                    }
                }
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        break;
                    } else {
                        // TODO: Handle this, could be some odd sort of failure
                        break;
                    }
                }
            }
        }
        resps
    }

    pub fn tick(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        let mut retrans = Vec::new();
        {
            let ref l = self.l;

            self.connections.retain(|id, conn| {
                if conn.last_updated.elapsed() > time::Duration::from_millis(TIMEOUT_MS) {
                    resps.push((conn.torrent, Err(ErrorKind::Timeout.into())));
                    debug!(l, "Announce {:?} timed out", id);
                    false
                } else{
                    if conn.last_retrans.elapsed() > time::Duration::from_millis(RETRANS_MS) {
                        debug!(l, "Retransmiting req {:?}", id);
                        retrans.push(*id);
                    }
                    true
                }
            });
        }

        for id in retrans {
            if let Some(r) = self.send_data(id) {
                resps.push(r)
            }
        }
        resps
    }

    fn process_connect(&mut self) -> Option<Response> {
        let (transaction_id, connection_id) = {
            let mut connect_resp = Cursor::new(&self.buf[4..16]);
            let tid = connect_resp.read_u32::<BigEndian>().unwrap();
            let cid  = connect_resp.read_u64::<BigEndian>().unwrap();
            (tid, cid)
        };

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let mut data = [0u8; 98];
        {
            let conn = match self.connections.get_mut(&id) {
                Some(conn) => conn,
                None => return None,
            };
            let addr = match conn.state {
                State::Connecting { addr, .. } => addr,
                _ => return None,
            };

            {
                let mut announce_req = Cursor::new(&mut data[..]);
                announce_req.write_u64::<BigEndian>(connection_id).unwrap();
                announce_req.write_u32::<BigEndian>(1).unwrap();

                let tid = random::<u32>();
                announce_req.write_u32::<BigEndian>(tid).unwrap();
                self.transactions.insert(tid, id);

                announce_req.write_all(&conn.announce.hash).unwrap();
                announce_req.write_all(&PEER_ID[..]).unwrap();
                announce_req.write_u64::<BigEndian>(conn.announce.downloaded as u64).unwrap();
                announce_req.write_u64::<BigEndian>(conn.announce.left as u64).unwrap();
                announce_req.write_u64::<BigEndian>(conn.announce.uploaded as u64).unwrap();
                match conn.announce.event {
                    Some(Event::Started) => {
                        announce_req.write_u32::<BigEndian>(2).unwrap();
                    }
                    Some(Event::Stopped) => {
                        announce_req.write_u32::<BigEndian>(3).unwrap();
                    }
                    Some(Event::Completed) => {
                        announce_req.write_u32::<BigEndian>(1).unwrap();
                    }
                    None => {
                        announce_req.write_u32::<BigEndian>(0).unwrap();
                    }
                }
            }
            conn.state = State::Announcing { addr, data };
            conn.last_updated = time::Instant::now();
        }
        self.send_data(id)
    }

    fn process_announce(&mut self, len: usize) -> Option<Response> {
        let mut announce_resp = Cursor::new(&self.buf[4..len]);
        let mut resp = TrackerResponse::empty();
        let transaction_id = announce_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        resp.interval = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.leechers = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.seeders = announce_resp.read_u32::<BigEndian>().unwrap();
        if len > 20 {
            for p in announce_resp.get_ref()[20..len].chunks(6) {
                let ip = Ipv4Addr::new(p[0], p[1], p[2], p[3]);
                let socket = SocketAddrV4::new(ip, (&p[4..]).read_u16::<BigEndian>().unwrap());
                resp.peers.push(SocketAddr::V4(socket));
            }
        }
        Some((conn.torrent, Ok(resp)))
    }

    fn process_error(&mut self, len: usize) -> Option<Response> {
        let mut s = String::new();
        let mut connect_resp = Cursor::new(&self.buf[4..len]);
        let transaction_id = connect_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        if connect_resp.read_to_string(&mut s).is_err() {
            Some((conn.torrent, Err(ErrorKind::InvalidResponse("Tracker error response was invalid UTF8").into())))
        } else {
            Some((conn.torrent, Err(ErrorKind::TrackerError(s).into())))
        }
    }

    fn new_conn(&mut self) -> usize {
        let c = self.conn_count;
        self.conn_count += 1;
        c
    }

    fn send_data(&mut self, id: usize) -> Option<Response> {
        let tid;
        let res = {
            let conn = self.connections.get_mut(&id).unwrap();
            tid = conn.torrent;
            // If this actually blocks, something is really fucked(prob with the NIC)
            // and i dont think we need to care
            match conn.state {
                State::Connecting { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                State::Announcing { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                _ => Ok(0)
            }
        };

        match res {
            Err(e) => {
                self.connections.remove(&id);
                Some((tid, Err(e)))
            }
            Ok(_) => None,
        }
    }
}
<commit_msg>Cleanup transactions in udp ticker<commit_after>use std::net::{UdpSocket, SocketAddr, Ipv4Addr, SocketAddrV4};
use std::time;
use tracker::{Announce, Result, ResultExt, Response, TrackerResponse, Event, Error, ErrorKind, dns};
use std::collections::HashMap;
use {CONFIG, PEER_ID, amy};
use std::sync::Arc;
use std::io::{self, Write, Read, Cursor};
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use slog::Logger;
use url::Url;
use rand::random;

// We're not going to bother with backoff, if the tracker/network aren't working now
// the torrent can just resend a request later.
const TIMEOUT_MS: u64 = 5000;
const RETRANS_MS: u64 = 500;

pub struct Handler {
    id: usize,
    sock: UdpSocket,
    connections: HashMap<usize, Connection>,
    transactions: HashMap<u32, usize>,
    conn_count: usize,
    l: Logger,
    buf: Vec<u8>,
}

struct Connection {
    torrent: usize,
    last_updated: time::Instant,
    last_retrans: time::Instant,
    state: State,
    announce: Announce,
}

enum State {
    ResolvingDNS { port: u16 },
    Connecting { addr: SocketAddr, data: [u8; 16] },
    Announcing { addr: SocketAddr, data: [u8; 98] },
}

impl Handler {
    pub fn new(reg: &Arc<amy::Registrar>, l: Logger) -> io::Result<Handler> {
        let port = CONFIG.port;
        let sock = UdpSocket::bind(("0.0.0.0", port))?;
        sock.set_nonblocking(true)?;
        let id = reg.register(&sock, amy::Event::Read)?;
        Ok(Handler {
            id,
            sock,
            connections: HashMap::new(),
            transactions: HashMap::new(),
            l,
            conn_count: 0,
            buf: vec![0u8; 350],
        })
    }

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

    pub fn complete(&self) -> bool {
        self.connections.is_empty()
    }

    pub fn contains(&self, id: usize) -> bool {
        self.connections.contains_key(&id)
    }

    pub fn new_announce(&mut self, req: Announce, url: &Url, dns: &mut dns::Resolver) -> Result<()> {
        debug!(self.l, "Received a new announce req for {:?}", url);
        let host = url.host_str().ok_or::<Error>(
            ErrorKind::InvalidRequest(format!("Tracker announce url has no host!")).into()
        )?;
        let port = url.port().ok_or::<Error>(
            ErrorKind::InvalidRequest(format!("Tracker announce url has no port!")).into()
        )?;

        let id = self.new_conn();
        self.connections.insert(id, Connection {
            torrent: req.id,
            last_updated: time::Instant::now(),
            last_retrans: time::Instant::now(),
            state: State::ResolvingDNS { port },
            announce: req,
        });
        debug!(self.l, "Dispatching DNS req for {:?}, url: {:?}", id, host);
        dns.new_query(id, host);
        Ok(())
    }

    pub fn dns_resolved(&mut self, resp: dns::QueryResponse) -> Option<Response> {
        let id = resp.id;
        let mut success = false;
        debug!(self.l, "Received a DNS resp for {:?}", id);
        let resp = if let Some(mut conn) = self.connections.get_mut(&id) {
            match conn.state {
                State::ResolvingDNS { port } => {
                    conn.last_updated = time::Instant::now();
                    let tid = random::<u32>();
                    let mut data = [0u8; 16];
                    {
                        let mut connect_req = Cursor::new(&mut data[..]);
                        connect_req.write_u64::<BigEndian>(0x41727101980).unwrap();
                        connect_req.write_u32::<BigEndian>(0).unwrap();
                        connect_req.write_u32::<BigEndian>(tid).unwrap();
                    }
                    match resp.res {
                        Ok(ip) => {
                            success = true;
                            conn.state = State::Connecting { addr: SocketAddr::new(ip, port), data };
                            self.transactions.insert(tid, id);
                            None
                        }
                        Err(e) => Some((conn.torrent, Err(e))),
                    }
                }
                _ => None,
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
            resp
        } else if success {
            self.send_data(id)
        } else {
            None
        }
    }

    pub fn readable(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        loop {
            match self.sock.recv_from(&mut self.buf[..]) {
                Ok((v, _)) => {
                    let action = (&self.buf[0..4]).read_u32::<BigEndian>().unwrap();
                    match action {
                        0 if v == 16 => {
                            if let Some(r) = self.process_connect() {
                                resps.push(r);
                            }
                        }
                        1 if v >= 20 => {
                            if let Some(r) = self.process_announce(v) {
                                resps.push(r);
                            }
                        }
                        3 if v >= 8 => {
                            if let Some(r) = self.process_error(v) {
                                resps.push(r);
                            }
                        }
                        _ => { debug!(self.l, "Received invalid response from tracker!") }
                    }
                }
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        break;
                    } else {
                        // TODO: Handle this, could be some odd sort of failure
                        break;
                    }
                }
            }
        }
        resps
    }

    pub fn tick(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        let mut retrans = Vec::new();
        {
            let ref l = self.l;

            self.connections.retain(|id, conn| {
                if conn.last_updated.elapsed() > time::Duration::from_millis(TIMEOUT_MS) {
                    resps.push((conn.torrent, Err(ErrorKind::Timeout.into())));
                    debug!(l, "Announce {:?} timed out", id);
                    false
                } else{
                    if conn.last_retrans.elapsed() > time::Duration::from_millis(RETRANS_MS) {
                        debug!(l, "Retransmiting req {:?}", id);
                        retrans.push(*id);
                    }
                    true
                }
            });

            let c = &self.connections;
            self.transactions.retain(|_, id| c.contains_key(id));
        }

        for id in retrans {
            if let Some(r) = self.send_data(id) {
                resps.push(r)
            }
        }
        resps
    }

    fn process_connect(&mut self) -> Option<Response> {
        let (transaction_id, connection_id) = {
            let mut connect_resp = Cursor::new(&self.buf[4..16]);
            let tid = connect_resp.read_u32::<BigEndian>().unwrap();
            let cid  = connect_resp.read_u64::<BigEndian>().unwrap();
            (tid, cid)
        };

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let mut data = [0u8; 98];
        {
            let conn = match self.connections.get_mut(&id) {
                Some(conn) => conn,
                None => return None,
            };
            let addr = match conn.state {
                State::Connecting { addr, .. } => addr,
                _ => return None,
            };

            {
                let mut announce_req = Cursor::new(&mut data[..]);
                announce_req.write_u64::<BigEndian>(connection_id).unwrap();
                announce_req.write_u32::<BigEndian>(1).unwrap();

                let tid = random::<u32>();
                announce_req.write_u32::<BigEndian>(tid).unwrap();
                self.transactions.insert(tid, id);

                announce_req.write_all(&conn.announce.hash).unwrap();
                announce_req.write_all(&PEER_ID[..]).unwrap();
                announce_req.write_u64::<BigEndian>(conn.announce.downloaded as u64).unwrap();
                announce_req.write_u64::<BigEndian>(conn.announce.left as u64).unwrap();
                announce_req.write_u64::<BigEndian>(conn.announce.uploaded as u64).unwrap();
                match conn.announce.event {
                    Some(Event::Started) => {
                        announce_req.write_u32::<BigEndian>(2).unwrap();
                    }
                    Some(Event::Stopped) => {
                        announce_req.write_u32::<BigEndian>(3).unwrap();
                    }
                    Some(Event::Completed) => {
                        announce_req.write_u32::<BigEndian>(1).unwrap();
                    }
                    None => {
                        announce_req.write_u32::<BigEndian>(0).unwrap();
                    }
                }
            }
            conn.state = State::Announcing { addr, data };
            conn.last_updated = time::Instant::now();
        }
        self.send_data(id)
    }

    fn process_announce(&mut self, len: usize) -> Option<Response> {
        let mut announce_resp = Cursor::new(&self.buf[4..len]);
        let mut resp = TrackerResponse::empty();
        let transaction_id = announce_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        resp.interval = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.leechers = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.seeders = announce_resp.read_u32::<BigEndian>().unwrap();
        if len > 20 {
            for p in announce_resp.get_ref()[20..len].chunks(6) {
                let ip = Ipv4Addr::new(p[0], p[1], p[2], p[3]);
                let socket = SocketAddrV4::new(ip, (&p[4..]).read_u16::<BigEndian>().unwrap());
                resp.peers.push(SocketAddr::V4(socket));
            }
        }
        Some((conn.torrent, Ok(resp)))
    }

    fn process_error(&mut self, len: usize) -> Option<Response> {
        let mut s = String::new();
        let mut connect_resp = Cursor::new(&self.buf[4..len]);
        let transaction_id = connect_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        if connect_resp.read_to_string(&mut s).is_err() {
            Some((conn.torrent, Err(ErrorKind::InvalidResponse("Tracker error response was invalid UTF8").into())))
        } else {
            Some((conn.torrent, Err(ErrorKind::TrackerError(s).into())))
        }
    }

    fn new_conn(&mut self) -> usize {
        let c = self.conn_count;
        self.conn_count += 1;
        c
    }

    fn send_data(&mut self, id: usize) -> Option<Response> {
        let tid;
        let res = {
            let conn = self.connections.get_mut(&id).unwrap();
            tid = conn.torrent;
            // If this actually blocks, something is really fucked(prob with the NIC)
            // and i dont think we need to care
            match conn.state {
                State::Connecting { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                State::Announcing { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                _ => Ok(0)
            }
        };

        match res {
            Err(e) => {
                self.connections.remove(&id);
                Some((tid, Err(e)))
            }
            Ok(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::{Result, Write};
use std::sync::Arc;
use std::option::Option;

use rocksdb::RateLimiter;

const PRIORITY_HIGH: u8 = 1;
const REFILL_PERIOD: i64 = 100 * 1000;
const FARENESS: i32 = 10;
const SNAP_MAX_BYTES_PER_TIME: i64 = 4 * 1024 * 1024;
pub const DEFAULT_SNAP_MAX_BYTES_PER_SEC: u64 = 30 * 1024 * 1024;

pub struct IOLimiter {
    inner: RateLimiter,
}

impl IOLimiter {
    pub fn new(bytes_per_sec: u64) -> IOLimiter {
        IOLimiter {
            inner: RateLimiter::new(bytes_per_sec as i64, REFILL_PERIOD, FARENESS),
        }
    }

    pub fn set_bytes_per_second(&self, bytes_per_sec: i64) {
        self.inner.set_bytes_per_second(bytes_per_sec)
    }

    pub fn request(&self, bytes: i64) {
        self.inner.request(bytes, PRIORITY_HIGH)
    }

    pub fn get_max_bytes_per_time(&self) -> i64 {
        if self.inner.get_singleburst_bytes() > SNAP_MAX_BYTES_PER_TIME {
            SNAP_MAX_BYTES_PER_TIME
        } else {
            self.inner.get_singleburst_bytes()
        }
    }

    pub fn get_total_bytes_through(&self) -> i64 {
        self.inner.get_total_bytes_through(PRIORITY_HIGH)
    }

    pub fn get_bytes_per_second(&self) -> i64 {
        self.inner.get_bytes_per_second()
    }

    pub fn get_total_requests(&self) -> i64 {
        self.inner.get_total_requests(PRIORITY_HIGH)
    }
}

pub struct LimitWriter<'a, T: Write + 'a> {
    limiter: Option<Arc<IOLimiter>>,
    writer: &'a mut T,
}

impl<'a, T: Write + 'a> LimitWriter<'a, T> {
    pub fn new(limiter: Option<Arc<IOLimiter>>, writer: &'a mut T) -> LimitWriter<'a, T> {
        LimitWriter {
            limiter: limiter,
            writer: writer,
        }
    }
}

impl<'a, T: Write + 'a> Write for LimitWriter<'a, T> {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let total = buf.len();
        if let Some(ref limiter) = self.limiter {
            let single = limiter.get_max_bytes_per_time() as usize;
            let mut curr = 0;
            let mut end;
            while curr < total {
                if curr + single >= total {
                    end = total;
                } else {
                    end = curr + single;
                }
                limiter.request((end - curr) as i64);
                self.writer.write_all(&buf[curr..end])?;
                curr = end;
            }
        } else {
            self.writer.write_all(buf)?;
        }
        Ok(total)
    }

    fn flush(&mut self) -> Result<()> {
        self.writer.flush()?;
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use std::fs::File;
    use std::io::{Read, Write};
    use std::sync::Arc;

    use super::{IOLimiter, LimitWriter, SNAP_MAX_BYTES_PER_TIME};

    #[test]
    fn test_io_limiter() {
        let limiter = IOLimiter::new(10 * 1024 * 1024);
        assert!(limiter.get_max_bytes_per_time() <= SNAP_MAX_BYTES_PER_TIME);

        limiter.set_bytes_per_second(20 * 1024 * 1024);
        assert_eq!(limiter.get_bytes_per_second(), 20 * 1024 * 1024);

        assert_eq!(limiter.get_total_bytes_through(), 0);

        limiter.request(1024 * 1024);
        assert_eq!(limiter.get_total_bytes_through(), 1024 * 1024);

        assert_eq!(limiter.get_total_requests(), 1);
    }

    #[test]
    fn test_limit_writer() {
        let mut file = File::create("/tmp/test_limit_writer.txt").unwrap();
        let mut limit_writer = LimitWriter::new(Some(Arc::new(IOLimiter::new(1024))), &mut file);

        let mut s = String::new();
        for _ in 0..100 {
            s.push_str("Hello, World!");
        }
        limit_writer.write_all(s.as_bytes()).unwrap();
        limit_writer.flush().unwrap();

        let mut file = File::open("/tmp/test_limit_writer.txt").unwrap();
        let mut contents = String::new();
        file.read_to_string(&mut contents).unwrap();
        assert_eq!(contents, s);
    }
}
<commit_msg>LimitWriter: test use TempDir (#2687)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::{Result, Write};
use std::sync::Arc;
use std::option::Option;

use rocksdb::RateLimiter;

const PRIORITY_HIGH: u8 = 1;
const REFILL_PERIOD: i64 = 100 * 1000;
const FARENESS: i32 = 10;
const SNAP_MAX_BYTES_PER_TIME: i64 = 4 * 1024 * 1024;
pub const DEFAULT_SNAP_MAX_BYTES_PER_SEC: u64 = 30 * 1024 * 1024;

pub struct IOLimiter {
    inner: RateLimiter,
}

impl IOLimiter {
    pub fn new(bytes_per_sec: u64) -> IOLimiter {
        IOLimiter {
            inner: RateLimiter::new(bytes_per_sec as i64, REFILL_PERIOD, FARENESS),
        }
    }

    pub fn set_bytes_per_second(&self, bytes_per_sec: i64) {
        self.inner.set_bytes_per_second(bytes_per_sec)
    }

    pub fn request(&self, bytes: i64) {
        self.inner.request(bytes, PRIORITY_HIGH)
    }

    pub fn get_max_bytes_per_time(&self) -> i64 {
        if self.inner.get_singleburst_bytes() > SNAP_MAX_BYTES_PER_TIME {
            SNAP_MAX_BYTES_PER_TIME
        } else {
            self.inner.get_singleburst_bytes()
        }
    }

    pub fn get_total_bytes_through(&self) -> i64 {
        self.inner.get_total_bytes_through(PRIORITY_HIGH)
    }

    pub fn get_bytes_per_second(&self) -> i64 {
        self.inner.get_bytes_per_second()
    }

    pub fn get_total_requests(&self) -> i64 {
        self.inner.get_total_requests(PRIORITY_HIGH)
    }
}

pub struct LimitWriter<'a, T: Write + 'a> {
    limiter: Option<Arc<IOLimiter>>,
    writer: &'a mut T,
}

impl<'a, T: Write + 'a> LimitWriter<'a, T> {
    pub fn new(limiter: Option<Arc<IOLimiter>>, writer: &'a mut T) -> LimitWriter<'a, T> {
        LimitWriter {
            limiter: limiter,
            writer: writer,
        }
    }
}

impl<'a, T: Write + 'a> Write for LimitWriter<'a, T> {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let total = buf.len();
        if let Some(ref limiter) = self.limiter {
            let single = limiter.get_max_bytes_per_time() as usize;
            let mut curr = 0;
            let mut end;
            while curr < total {
                if curr + single >= total {
                    end = total;
                } else {
                    end = curr + single;
                }
                limiter.request((end - curr) as i64);
                self.writer.write_all(&buf[curr..end])?;
                curr = end;
            }
        } else {
            self.writer.write_all(buf)?;
        }
        Ok(total)
    }

    fn flush(&mut self) -> Result<()> {
        self.writer.flush()?;
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use tempdir::TempDir;
    use std::fs::File;
    use std::io::{Read, Write};
    use std::sync::Arc;

    use super::{IOLimiter, LimitWriter, SNAP_MAX_BYTES_PER_TIME};

    #[test]
    fn test_io_limiter() {
        let limiter = IOLimiter::new(10 * 1024 * 1024);
        assert!(limiter.get_max_bytes_per_time() <= SNAP_MAX_BYTES_PER_TIME);

        limiter.set_bytes_per_second(20 * 1024 * 1024);
        assert_eq!(limiter.get_bytes_per_second(), 20 * 1024 * 1024);

        assert_eq!(limiter.get_total_bytes_through(), 0);

        limiter.request(1024 * 1024);
        assert_eq!(limiter.get_total_bytes_through(), 1024 * 1024);

        assert_eq!(limiter.get_total_requests(), 1);
    }

    #[test]
    fn test_limit_writer() {
        let dir = TempDir::new("_test_limit_writer").expect("");
        let path = dir.path().join("test-file");
        let mut file = File::create(&path).unwrap();
        let mut limit_writer = LimitWriter::new(Some(Arc::new(IOLimiter::new(1024))), &mut file);

        let mut s = String::new();
        for _ in 0..100 {
            s.push_str("Hello, World!");
        }
        limit_writer.write_all(s.as_bytes()).unwrap();
        limit_writer.flush().unwrap();

        let mut file = File::open(&path).unwrap();
        let mut contents = String::new();
        file.read_to_string(&mut contents).unwrap();
        assert_eq!(contents, s);
    }
}
<|endoftext|>


<commit_before>use core::clone::Clone;

use common::string::*;
use common::url::*;

use filesystems::unfs::*;

use programs::session::*;

pub struct FileScheme;

impl SessionScheme for FileScheme {
    fn scheme(&self) -> String {
        return "file".to_string();
    }

    #[allow(unused_variables)]
    fn on_url(&mut self, session: &Session, url: &URL) -> String {
        let unfs = UnFS::new();

        let mut path = String::new();
        for part in url.path.as_slice(){
            if path.len() > 0 {
                path = path + "/" + part.clone();
            }else{
                path = part.clone();
            }
        }

        let mut ret = String::new();
        for file in unfs.list(path.clone()).as_slice() {
            ret = ret + file.clone() + "\n";
        }
        return ret;
    }
}
<commit_msg>Fix file scheme empty line<commit_after>use core::clone::Clone;

use common::string::*;
use common::url::*;

use filesystems::unfs::*;

use programs::session::*;

pub struct FileScheme;

impl SessionScheme for FileScheme {
    fn scheme(&self) -> String {
        return "file".to_string();
    }

    #[allow(unused_variables)]
    fn on_url(&mut self, session: &Session, url: &URL) -> String {
        let unfs = UnFS::new();

        let mut path = String::new();
        for part in url.path.as_slice(){
            if path.len() > 0 {
                path = path + "/" + part.clone();
            }else{
                path = part.clone();
            }
        }

        let mut ret = String::new();
        for file in unfs.list(path.clone()).as_slice() {
            if ret.len() > 0 {
                ret = ret + "\n" + file.clone();
            }else{
                ret = file.clone();
            }
        }
        return ret;
    }
}
<|endoftext|>


<commit_before>use bytecount;
use crossbeam::crossbeam_channel::{unbounded, Sender};
use fnv::FnvHashMap;
use ignore::{overrides, WalkBuilder, WalkState};
use num_cpus;
use std::fs::File;
use std::io::{self, Read};
use std::path::PathBuf;

use crate::cli;
use crate::lang;

pub fn visit_path_parallel(path: &PathBuf, globs: Vec<&str>) -> Vec<cli::LangOut> {
    let (ch_s, ch_r) = unbounded();
    let overrides = parse_overrides(path, globs);

    WalkBuilder::new(path)
        .threads(num_cpus::get() + 1)
        .overrides(overrides)
        .build_parallel()
        .run(|| {
            let mut buf = [0u8; 1 << 13];
            let mut map = Map {
                s: ch_s.clone(),
                map: FnvHashMap::default(),
            };
            Box::new(move |result| {
                let entry = match result {
                    Err(err) => {
                        println!("Error: {}", err);
                        return WalkState::Continue;
                    }
                    Ok(entry) => entry,
                };
                let path = entry.into_path();
                if path.is_dir() {
                    return WalkState::Continue;
                }
                let ext = match path.extension() {
                    None => return WalkState::Continue,
                    Some(ext) => ext,
                };
                let ext_str = match ext.to_str() {
                    None => return WalkState::Continue,
                    Some(ext_str) => ext_str,
                };
                let language = match lang::get_language(ext_str.to_ascii_lowercase().as_str()) {
                    None => return WalkState::Continue,
                    Some(lang) => lang,
                };
                match lines_in_file(&path, &mut buf) {
                    Ok(lines) => {
                        let counter = map.map.entry(language).or_insert_with(LangResult::new);
                        counter.file_cnt += 1;
                        counter.line_cnt += lines;
                    }
                    Err(err) => {
                        println!("Error in {:?}: {}", &path, err);
                    }
                }
                WalkState::Continue
            })
        });
    drop(ch_s);

    let mut langs = FnvHashMap::default();
    for m in ch_r.iter() {
        for (&key, val) in m.iter() {
            let l = langs.entry(key).or_insert_with(LangResult::new);
            l.file_cnt += val.file_cnt;
            l.line_cnt += val.line_cnt;
        }
    }
    map_to_vec(langs)
}

fn lines_in_file(path: &PathBuf, buf: &mut [u8]) -> io::Result<u64> {
    let mut file = File::open(path.as_path())?;
    let mut cnt = 1;
    loop {
        let n = file.read(buf)?;
        if n == 0 {
            return Ok(cnt as u64);
        }
        cnt += bytecount::count(&buf[0..n], b'\n');
    }
}

fn parse_overrides(path: &PathBuf, globs: Vec<&str>) -> overrides::Override {
    let mut override_builder = overrides::OverrideBuilder::new(path);
    for glob in globs.iter() {
        override_builder.add(glob).unwrap();
    }
    override_builder.build().unwrap()
}

fn map_to_vec(map: FnvHashMap<lang::Language, LangResult>) -> Vec<cli::LangOut> {
    let mut langs = Vec::with_capacity(map.len());
    for (key, val) in map.iter() {
        langs.push(cli::LangOut {
            language: *key,
            num_files: val.file_cnt,
            num_lines: val.line_cnt,
        });
    }
    langs.sort_by(|a, b| a.num_lines.cmp(&b.num_lines).reverse());
    langs
}

struct Map {
    s: Sender<FnvHashMap<lang::Language, LangResult>>,
    map: FnvHashMap<lang::Language, LangResult>,
}

impl Drop for Map {
    fn drop(&mut self) {
        self.s.send(self.map.clone()).unwrap();
    }
}

#[derive(Clone, Copy, Debug)]
struct LangResult {
    file_cnt: u64,
    line_cnt: u64,
}

impl LangResult {
    fn new() -> Self {
        LangResult {
            file_cnt: 0,
            line_cnt: 0,
        }
    }
}
<commit_msg>Fix crossbeam import<commit_after>use bytecount;
use crossbeam::channel::{unbounded, Sender};
use fnv::FnvHashMap;
use ignore::{overrides, WalkBuilder, WalkState};
use num_cpus;
use std::fs::File;
use std::io::{self, Read};
use std::path::PathBuf;

use crate::cli;
use crate::lang;

pub fn visit_path_parallel(path: &PathBuf, globs: Vec<&str>) -> Vec<cli::LangOut> {
    let (ch_s, ch_r) = unbounded();
    let overrides = parse_overrides(path, globs);

    WalkBuilder::new(path)
        .threads(num_cpus::get() + 1)
        .overrides(overrides)
        .build_parallel()
        .run(|| {
            let mut buf = [0u8; 1 << 13];
            let mut map = Map {
                s: ch_s.clone(),
                map: FnvHashMap::default(),
            };
            Box::new(move |result| {
                let entry = match result {
                    Err(err) => {
                        println!("Error: {}", err);
                        return WalkState::Continue;
                    }
                    Ok(entry) => entry,
                };
                let path = entry.into_path();
                if path.is_dir() {
                    return WalkState::Continue;
                }
                let ext = match path.extension() {
                    None => return WalkState::Continue,
                    Some(ext) => ext,
                };
                let ext_str = match ext.to_str() {
                    None => return WalkState::Continue,
                    Some(ext_str) => ext_str,
                };
                let language = match lang::get_language(ext_str.to_ascii_lowercase().as_str()) {
                    None => return WalkState::Continue,
                    Some(lang) => lang,
                };
                match lines_in_file(&path, &mut buf) {
                    Ok(lines) => {
                        let counter = map.map.entry(language).or_insert_with(LangResult::new);
                        counter.file_cnt += 1;
                        counter.line_cnt += lines;
                    }
                    Err(err) => {
                        println!("Error in {:?}: {}", &path, err);
                    }
                }
                WalkState::Continue
            })
        });
    drop(ch_s);

    let mut langs = FnvHashMap::default();
    for m in ch_r.iter() {
        for (&key, val) in m.iter() {
            let l = langs.entry(key).or_insert_with(LangResult::new);
            l.file_cnt += val.file_cnt;
            l.line_cnt += val.line_cnt;
        }
    }
    map_to_vec(langs)
}

fn lines_in_file(path: &PathBuf, buf: &mut [u8]) -> io::Result<u64> {
    let mut file = File::open(path.as_path())?;
    let mut cnt = 1;
    loop {
        let n = file.read(buf)?;
        if n == 0 {
            return Ok(cnt as u64);
        }
        cnt += bytecount::count(&buf[0..n], b'\n');
    }
}

fn parse_overrides(path: &PathBuf, globs: Vec<&str>) -> overrides::Override {
    let mut override_builder = overrides::OverrideBuilder::new(path);
    for glob in globs.iter() {
        override_builder.add(glob).unwrap();
    }
    override_builder.build().unwrap()
}

fn map_to_vec(map: FnvHashMap<lang::Language, LangResult>) -> Vec<cli::LangOut> {
    let mut langs = Vec::with_capacity(map.len());
    for (key, val) in map.iter() {
        langs.push(cli::LangOut {
            language: *key,
            num_files: val.file_cnt,
            num_lines: val.line_cnt,
        });
    }
    langs.sort_by(|a, b| a.num_lines.cmp(&b.num_lines).reverse());
    langs
}

struct Map {
    s: Sender<FnvHashMap<lang::Language, LangResult>>,
    map: FnvHashMap<lang::Language, LangResult>,
}

impl Drop for Map {
    fn drop(&mut self) {
        self.s.send(self.map.clone()).unwrap();
    }
}

#[derive(Clone, Copy, Debug)]
struct LangResult {
    file_cnt: u64,
    line_cnt: u64,
}

impl LangResult {
    fn new() -> Self {
        LangResult {
            file_cnt: 0,
            line_cnt: 0,
        }
    }
}
<|endoftext|>