<commit_before>use std::os::raw::c_void;
use raw::Local;

extern "system" {

    #[link_name = "NeonSys_Module_ExecKernel"]
    pub fn exec_kernel(kernel: *mut c_void, callback: extern fn(*mut c_void, *mut c_void, *mut c_void), exports: Local, scope: *mut c_void);

}
<commit_msg>expand neon_sys::module mod documentation<commit_after>//! A helper function for initializing a module.

use std::os::raw::c_void;
use raw::Local;

extern "system" {

    /// Creates a new `v8::HandleScope` and calls `callback` provided with the argument signature
    /// `(kernal, exports, scope)`.
    #[link_name = "NeonSys_Module_ExecKernel"]
    pub fn exec_kernel(kernel: *mut c_void, callback: extern fn(*mut c_void, *mut c_void, *mut c_void), exports: Local, scope: *mut c_void);

}
<|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/. */

//! An actor-based remote devtools server implementation. Only tested with
//! nightly Firefox versions at time of writing. Largely based on
//! reverse-engineering of Firefox chrome devtool logs and reading of
//! [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).

#![crate_name = "devtools"]
#![crate_type = "rlib"]

#![feature(box_syntax)]
#![feature(core)]
#![feature(custom_derive)]
#![feature(get_type_id)]
#![feature(plugin)]
#![feature(raw)]
#![feature(reflect_marker)]
#![plugin(serde_macros)]

#![allow(non_snake_case)]

#[macro_use]
extern crate log;

extern crate core;
extern crate devtools_traits;
extern crate rustc_serialize;
extern crate ipc_channel;
extern crate serde;
extern crate msg;
extern crate time;
extern crate util;
extern crate hyper;
extern crate url;

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::network_event::{NetworkEventActor, EventActor, ResponseStartMsg};
use actors::framerate::FramerateActor;
use actors::inspector::InspectorActor;
use actors::object::ObjectActor;
use actors::root::RootActor;
use actors::tab::TabActor;
use actors::timeline::TimelineActor;
use actors::worker::WorkerActor;
use protocol::JsonPacketStream;

use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg};
use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg, LogLevel, NetworkEvent};
use devtools_traits::{ScriptToDevtoolsControlMsg};
use msg::constellation_msg::{PipelineId, WorkerId};
use util::task::spawn_named;

use ipc_channel::ipc::IpcSender;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::error::Error;
use std::sync::mpsc::{channel, Receiver, Sender, RecvError};
use std::net::{TcpListener, TcpStream, Shutdown};
use std::sync::{Arc, Mutex};
use time::precise_time_ns;

mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
    pub mod console;
    pub mod framerate;
    pub mod inspector;
    pub mod memory;
    pub mod network_event;
    pub mod object;
    pub mod root;
    pub mod tab;
    pub mod timeline;
    pub mod worker;
}
mod protocol;

#[derive(RustcEncodable)]
struct ConsoleAPICall {
    from: String,
    __type__: String,
    message: ConsoleMsg,
}

#[derive(RustcEncodable)]
struct ConsoleMsg {
    level: String,
    timeStamp: u64,
    arguments: Vec<String>,
    filename: String,
    lineNumber: u32,
    columnNumber: u32,
}

#[derive(RustcEncodable)]
struct NetworkEventMsg {
    from: String,
    __type__: String,
    eventActor: EventActor,
}

#[derive(RustcEncodable)]
struct NetworkEventUpdateMsg {
    from: String,
    __type__: String,
    updateType: String,
    response: ResponseStartMsg,
}

/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
    let (sender, receiver) = channel();
    {
        let sender = sender.clone();
        spawn_named("Devtools".to_owned(), move || {
            run_server(sender, receiver, port)
        });
    }
    sender
}

fn run_server(sender: Sender<DevtoolsControlMsg>,
              receiver: Receiver<DevtoolsControlMsg>,
              port: u16) {
    let listener = TcpListener::bind(&("127.0.0.1", port)).unwrap();

    let mut registry = ActorRegistry::new();

    let root = box RootActor {
        tabs: vec!(),
    };

    registry.register(root);
    registry.find::<RootActor>("root");

    let actors = registry.create_shareable();

    let mut accepted_connections: Vec<TcpStream> = Vec::new();

    let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();
    let mut actor_requests: HashMap<String, String> = HashMap::new();

    let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new();

    /// Process the input from a single devtools client until EOF.
    fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
        println!("connection established to {}", stream.peer_addr().unwrap());
        {
            let actors = actors.lock().unwrap();
            let msg = actors.find::<RootActor>("root").encodable();
            stream.write_json_packet(&msg);
        }

        'outer: loop {
            match stream.read_json_packet() {
                Ok(Some(json_packet)) => {
                    match actors.lock().unwrap().handle_message(json_packet.as_object().unwrap(),
                                                                &mut stream) {
                        Ok(()) => {},
                        Err(()) => {
                            println!("error: devtools actor stopped responding");
                            let _ = stream.shutdown(Shutdown::Both);
                            break 'outer
                        }
                    }
                }
                Ok(None) => {
                    println!("error: EOF");
                    break 'outer
                }
                Err(err_msg) => {
                    println!("error: {}", err_msg);
                    break 'outer
                }
            }
        }
    }

    fn handle_framerate_tick(actors: Arc<Mutex<ActorRegistry>>, actor_name: String, tick: f64) {
        let actors = actors.lock().unwrap();
        let framerate_actor = actors.find::<FramerateActor>(&actor_name);
        framerate_actor.add_tick(tick);
    }

    // We need separate actor representations for each script global that exists;
    // clients can theoretically connect to multiple globals simultaneously.
    // TODO: move this into the root or tab modules?
    fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
                         ids: (PipelineId, Option<WorkerId>),
                         script_sender: IpcSender<DevtoolScriptControlMsg>,
                         devtools_sender: Sender<DevtoolsControlMsg>,
                         actor_pipelines: &mut HashMap<PipelineId, String>,
                         actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
                         page_info: DevtoolsPageInfo) {
        let mut actors = actors.lock().unwrap();

        let (pipeline, worker_id) = ids;

        //TODO: move all this actor creation into a constructor method on TabActor
        let (tab, console, inspector, timeline) = {
            let console = ConsoleActor {
                name: actors.new_name("console"),
                script_chan: script_sender.clone(),
                pipeline: pipeline,
                streams: RefCell::new(Vec::new()),
            };
            let inspector = InspectorActor {
                name: actors.new_name("inspector"),
                walker: RefCell::new(None),
                pageStyle: RefCell::new(None),
                highlighter: RefCell::new(None),
                script_chan: script_sender.clone(),
                pipeline: pipeline,
            };

            let timeline = TimelineActor::new(actors.new_name("timeline"),
                                              pipeline,
                                              script_sender,
                                              devtools_sender);

            let DevtoolsPageInfo { title, url } = page_info;
            let tab = TabActor {
                name: actors.new_name("tab"),
                title: title,
                url: url.serialize(),
                console: console.name(),
                inspector: inspector.name(),
                timeline: timeline.name(),
            };

            let root = actors.find_mut::<RootActor>("root");
            root.tabs.push(tab.name.clone());
            (tab, console, inspector, timeline)
        };

        if let Some(id) = worker_id {
            let worker = WorkerActor {
                name: actors.new_name("worker"),
                console: console.name(),
                id: id,
            };
            actor_workers.insert((pipeline, id), worker.name.clone());
            actors.register(box worker);
        }

        actor_pipelines.insert(pipeline, tab.name.clone());
        actors.register(box tab);
        actors.register(box console);
        actors.register(box inspector);
        actors.register(box timeline);
    }

    fn handle_console_message(actors: Arc<Mutex<ActorRegistry>>,
                              id: PipelineId,
                              worker_id: Option<WorkerId>,
                              console_message: ConsoleMessage,
                              actor_pipelines: &HashMap<PipelineId, String>,
                              actor_workers: &HashMap<(PipelineId, WorkerId), String>) {
        let console_actor_name = match find_console_actor(actors.clone(), id, worker_id, actor_workers,
                                                          actor_pipelines) {
            Some(name) => name,
            None => return,
        };
        let actors = actors.lock().unwrap();
        let console_actor = actors.find::<ConsoleActor>(&console_actor_name);
        let msg = ConsoleAPICall {
            from: console_actor.name.clone(),
            __type__: "consoleAPICall".to_string(),
            message: ConsoleMsg {
                level: match console_message.logLevel {
                    LogLevel::Debug => "debug",
                    LogLevel::Info => "info",
                    LogLevel::Warn => "warn",
                    LogLevel::Error => "error",
                    _ => "log"
                }.to_string(),
                timeStamp: precise_time_ns(),
                arguments: vec!(console_message.message),
                filename: console_message.filename,
                lineNumber: console_message.lineNumber,
                columnNumber: console_message.columnNumber,
            },
        };
        for stream in console_actor.streams.borrow_mut().iter_mut() {
            stream.write_json_packet(&msg);
        }
    }

    fn find_console_actor(actors: Arc<Mutex<ActorRegistry>>,
                          id: PipelineId,
                          worker_id: Option<WorkerId>,
                          actor_workers: &HashMap<(PipelineId, WorkerId), String>,
                          actor_pipelines: &HashMap<PipelineId, String>) -> Option<String> {
        let actors = actors.lock().unwrap();
        if let Some(worker_id) = worker_id {
            let actor_name = match (*actor_workers).get(&(id, worker_id)) {
                Some(name) => name,
                None => return None,
            };
            Some(actors.find::<WorkerActor>(actor_name).console.clone())
        } else {
            let actor_name = match (*actor_pipelines).get(&id) {
                Some(name) => name,
                None => return None,
            };
            Some(actors.find::<TabActor>(actor_name).console.clone())
        }
    }

    fn handle_network_event(actors: Arc<Mutex<ActorRegistry>>,
                            mut connections: Vec<TcpStream>,
                            actor_pipelines: &HashMap<PipelineId, String>,
                            actor_requests: &mut HashMap<String, String>,
                            actor_workers: &HashMap<(PipelineId, WorkerId), String>,
                            pipeline_id: PipelineId,
                            request_id: String,
                            network_event: NetworkEvent) {

        let console_actor_name = match find_console_actor(actors.clone(), pipeline_id, None,
                                                          actor_workers, actor_pipelines) {
            Some(name) => name,
            None => return,
        };
        let netevent_actor_name = find_network_event_actor(actors.clone(), actor_requests, request_id.clone());
        let mut actors = actors.lock().unwrap();
        let actor = actors.find_mut::<NetworkEventActor>(&netevent_actor_name);

        match network_event {
            NetworkEvent::HttpRequest(url, method, headers, body) => {
                //Store the request information in the actor
                actor.add_request(url, method, headers, body);

                //Send a networkEvent message to the client
                let msg = NetworkEventMsg {
                    from: console_actor_name,
                    __type__: "networkEvent".to_string(),
                    eventActor: actor.event_actor(),
                };
                for stream in connections.iter_mut() {
                    stream.write_json_packet(&msg);
                }
            }
            NetworkEvent::HttpResponse(headers, status, body) => {
                //Store the response information in the actor
                actor.add_response(headers, status, body);

                //Send a networkEventUpdate (responseStart) to the client
                let msg = NetworkEventUpdateMsg {
                    from: netevent_actor_name,
                    __type__: "networkEventUpdate".to_string(),
                    updateType: "responseStart".to_string(),
                    response: actor.response_start()
                };

                for stream in connections.iter_mut() {
                    stream.write_json_packet(&msg);
                }
            }
            //TODO: Send the other types of update messages at appropriate times
            //      requestHeaders, requestCookies, responseHeaders, securityInfo, etc
        }
    }

    // Find the name of NetworkEventActor corresponding to request_id
    // Create a new one if it does not exist, add it to the actor_requests hashmap
    fn find_network_event_actor(actors: Arc<Mutex<ActorRegistry>>,
                                actor_requests: &mut HashMap<String, String>,
                                request_id: String) -> String {
        let mut actors = actors.lock().unwrap();
        match (*actor_requests).entry(request_id) {
            Occupied(name) => {
                //TODO: Delete from map like Firefox does?
                name.into_mut().clone()
            }
            Vacant(entry) => {
                let actor_name = actors.new_name("netevent");
                let actor = NetworkEventActor::new(actor_name.clone());
                entry.insert(actor_name.clone());
                actors.register(box actor);
                actor_name
            }
        }
    }

    let sender_clone = sender.clone();
    spawn_named("DevtoolsClientAcceptor".to_owned(), move || {
        // accept connections and process them, spawning a new task for each one
        for stream in listener.incoming() {
            // connection succeeded
            sender_clone.send(DevtoolsControlMsg::FromChrome(
                    ChromeToDevtoolsControlMsg::AddClient(stream.unwrap()))).unwrap();
        }
    });

    loop {
        match receiver.recv() {
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream))) => {
                let actors = actors.clone();
                accepted_connections.push(stream.try_clone().unwrap());
                spawn_named("DevtoolsClientHandler".to_owned(), move || {
                    handle_client(actors, stream.try_clone().unwrap())
                })
            }
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::FramerateTick(
                        actor_name, tick))) =>
                handle_framerate_tick(actors.clone(), actor_name, tick),
            Ok(DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal(
                        ids, script_sender, pageinfo))) =>
                handle_new_global(actors.clone(), ids, script_sender, sender.clone(), &mut actor_pipelines,
                                  &mut actor_workers, pageinfo),
            Ok(DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::SendConsoleMessage(
                        id,
                        console_message,
                        worker_id))) =>
                handle_console_message(actors.clone(), id, worker_id, console_message,
                                       &actor_pipelines, &actor_workers),
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEventMessage(
                        request_id, network_event))) => {
                // copy the accepted_connections vector
                let mut connections = Vec::<TcpStream>::new();
                for stream in accepted_connections.iter() {
                    connections.push(stream.try_clone().unwrap());
                }
                //TODO: Get pipeline_id from NetworkEventMessage after fixing the send in http_loader
                // For now, the id of the first pipeline is passed
                handle_network_event(actors.clone(), connections, &actor_pipelines, &mut actor_requests,
                                     &actor_workers, PipelineId(0), request_id, network_event);
            },
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg)) |
            Err(RecvError) => break
        }
    }
    for connection in accepted_connections.iter_mut() {
        let _ = connection.shutdown(Shutdown::Both);
    }
}
<commit_msg>Auto merge of #7123 - Ms2ger:warnings, r=saneyuki<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/. */

//! An actor-based remote devtools server implementation. Only tested with
//! nightly Firefox versions at time of writing. Largely based on
//! reverse-engineering of Firefox chrome devtool logs and reading of
//! [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).

#![crate_name = "devtools"]
#![crate_type = "rlib"]

#![feature(box_syntax)]
#![feature(core)]
#![feature(custom_derive)]
#![feature(get_type_id)]
#![feature(plugin)]
#![feature(raw)]
#![feature(reflect_marker)]
#![plugin(serde_macros)]

#![allow(non_snake_case)]

#[macro_use]
extern crate log;

extern crate core;
extern crate devtools_traits;
extern crate rustc_serialize;
extern crate ipc_channel;
extern crate serde;
extern crate msg;
extern crate time;
extern crate util;
extern crate hyper;
extern crate url;

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::network_event::{NetworkEventActor, EventActor, ResponseStartMsg};
use actors::framerate::FramerateActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
use actors::tab::TabActor;
use actors::timeline::TimelineActor;
use actors::worker::WorkerActor;
use protocol::JsonPacketStream;

use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg};
use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg, LogLevel, NetworkEvent};
use devtools_traits::{ScriptToDevtoolsControlMsg};
use msg::constellation_msg::{PipelineId, WorkerId};
use util::task::spawn_named;

use ipc_channel::ipc::IpcSender;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::error::Error;
use std::sync::mpsc::{channel, Receiver, Sender, RecvError};
use std::net::{TcpListener, TcpStream, Shutdown};
use std::sync::{Arc, Mutex};
use time::precise_time_ns;

mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
    pub mod console;
    pub mod framerate;
    pub mod inspector;
    pub mod memory;
    pub mod network_event;
    pub mod object;
    pub mod root;
    pub mod tab;
    pub mod timeline;
    pub mod worker;
}
mod protocol;

#[derive(RustcEncodable)]
struct ConsoleAPICall {
    from: String,
    __type__: String,
    message: ConsoleMsg,
}

#[derive(RustcEncodable)]
struct ConsoleMsg {
    level: String,
    timeStamp: u64,
    arguments: Vec<String>,
    filename: String,
    lineNumber: u32,
    columnNumber: u32,
}

#[derive(RustcEncodable)]
struct NetworkEventMsg {
    from: String,
    __type__: String,
    eventActor: EventActor,
}

#[derive(RustcEncodable)]
struct NetworkEventUpdateMsg {
    from: String,
    __type__: String,
    updateType: String,
    response: ResponseStartMsg,
}

/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
    let (sender, receiver) = channel();
    {
        let sender = sender.clone();
        spawn_named("Devtools".to_owned(), move || {
            run_server(sender, receiver, port)
        });
    }
    sender
}

fn run_server(sender: Sender<DevtoolsControlMsg>,
              receiver: Receiver<DevtoolsControlMsg>,
              port: u16) {
    let listener = TcpListener::bind(&("127.0.0.1", port)).unwrap();

    let mut registry = ActorRegistry::new();

    let root = box RootActor {
        tabs: vec!(),
    };

    registry.register(root);
    registry.find::<RootActor>("root");

    let actors = registry.create_shareable();

    let mut accepted_connections: Vec<TcpStream> = Vec::new();

    let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();
    let mut actor_requests: HashMap<String, String> = HashMap::new();

    let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new();

    /// Process the input from a single devtools client until EOF.
    fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
        println!("connection established to {}", stream.peer_addr().unwrap());
        {
            let actors = actors.lock().unwrap();
            let msg = actors.find::<RootActor>("root").encodable();
            stream.write_json_packet(&msg);
        }

        'outer: loop {
            match stream.read_json_packet() {
                Ok(Some(json_packet)) => {
                    match actors.lock().unwrap().handle_message(json_packet.as_object().unwrap(),
                                                                &mut stream) {
                        Ok(()) => {},
                        Err(()) => {
                            println!("error: devtools actor stopped responding");
                            let _ = stream.shutdown(Shutdown::Both);
                            break 'outer
                        }
                    }
                }
                Ok(None) => {
                    println!("error: EOF");
                    break 'outer
                }
                Err(err_msg) => {
                    println!("error: {}", err_msg);
                    break 'outer
                }
            }
        }
    }

    fn handle_framerate_tick(actors: Arc<Mutex<ActorRegistry>>, actor_name: String, tick: f64) {
        let actors = actors.lock().unwrap();
        let framerate_actor = actors.find::<FramerateActor>(&actor_name);
        framerate_actor.add_tick(tick);
    }

    // We need separate actor representations for each script global that exists;
    // clients can theoretically connect to multiple globals simultaneously.
    // TODO: move this into the root or tab modules?
    fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
                         ids: (PipelineId, Option<WorkerId>),
                         script_sender: IpcSender<DevtoolScriptControlMsg>,
                         devtools_sender: Sender<DevtoolsControlMsg>,
                         actor_pipelines: &mut HashMap<PipelineId, String>,
                         actor_workers: &mut HashMap<(PipelineId, WorkerId), String>,
                         page_info: DevtoolsPageInfo) {
        let mut actors = actors.lock().unwrap();

        let (pipeline, worker_id) = ids;

        //TODO: move all this actor creation into a constructor method on TabActor
        let (tab, console, inspector, timeline) = {
            let console = ConsoleActor {
                name: actors.new_name("console"),
                script_chan: script_sender.clone(),
                pipeline: pipeline,
                streams: RefCell::new(Vec::new()),
            };
            let inspector = InspectorActor {
                name: actors.new_name("inspector"),
                walker: RefCell::new(None),
                pageStyle: RefCell::new(None),
                highlighter: RefCell::new(None),
                script_chan: script_sender.clone(),
                pipeline: pipeline,
            };

            let timeline = TimelineActor::new(actors.new_name("timeline"),
                                              pipeline,
                                              script_sender,
                                              devtools_sender);

            let DevtoolsPageInfo { title, url } = page_info;
            let tab = TabActor {
                name: actors.new_name("tab"),
                title: title,
                url: url.serialize(),
                console: console.name(),
                inspector: inspector.name(),
                timeline: timeline.name(),
            };

            let root = actors.find_mut::<RootActor>("root");
            root.tabs.push(tab.name.clone());
            (tab, console, inspector, timeline)
        };

        if let Some(id) = worker_id {
            let worker = WorkerActor {
                name: actors.new_name("worker"),
                console: console.name(),
                id: id,
            };
            actor_workers.insert((pipeline, id), worker.name.clone());
            actors.register(box worker);
        }

        actor_pipelines.insert(pipeline, tab.name.clone());
        actors.register(box tab);
        actors.register(box console);
        actors.register(box inspector);
        actors.register(box timeline);
    }

    fn handle_console_message(actors: Arc<Mutex<ActorRegistry>>,
                              id: PipelineId,
                              worker_id: Option<WorkerId>,
                              console_message: ConsoleMessage,
                              actor_pipelines: &HashMap<PipelineId, String>,
                              actor_workers: &HashMap<(PipelineId, WorkerId), String>) {
        let console_actor_name = match find_console_actor(actors.clone(), id, worker_id, actor_workers,
                                                          actor_pipelines) {
            Some(name) => name,
            None => return,
        };
        let actors = actors.lock().unwrap();
        let console_actor = actors.find::<ConsoleActor>(&console_actor_name);
        let msg = ConsoleAPICall {
            from: console_actor.name.clone(),
            __type__: "consoleAPICall".to_string(),
            message: ConsoleMsg {
                level: match console_message.logLevel {
                    LogLevel::Debug => "debug",
                    LogLevel::Info => "info",
                    LogLevel::Warn => "warn",
                    LogLevel::Error => "error",
                    _ => "log"
                }.to_string(),
                timeStamp: precise_time_ns(),
                arguments: vec!(console_message.message),
                filename: console_message.filename,
                lineNumber: console_message.lineNumber,
                columnNumber: console_message.columnNumber,
            },
        };
        for stream in console_actor.streams.borrow_mut().iter_mut() {
            stream.write_json_packet(&msg);
        }
    }

    fn find_console_actor(actors: Arc<Mutex<ActorRegistry>>,
                          id: PipelineId,
                          worker_id: Option<WorkerId>,
                          actor_workers: &HashMap<(PipelineId, WorkerId), String>,
                          actor_pipelines: &HashMap<PipelineId, String>) -> Option<String> {
        let actors = actors.lock().unwrap();
        if let Some(worker_id) = worker_id {
            let actor_name = match (*actor_workers).get(&(id, worker_id)) {
                Some(name) => name,
                None => return None,
            };
            Some(actors.find::<WorkerActor>(actor_name).console.clone())
        } else {
            let actor_name = match (*actor_pipelines).get(&id) {
                Some(name) => name,
                None => return None,
            };
            Some(actors.find::<TabActor>(actor_name).console.clone())
        }
    }

    fn handle_network_event(actors: Arc<Mutex<ActorRegistry>>,
                            mut connections: Vec<TcpStream>,
                            actor_pipelines: &HashMap<PipelineId, String>,
                            actor_requests: &mut HashMap<String, String>,
                            actor_workers: &HashMap<(PipelineId, WorkerId), String>,
                            pipeline_id: PipelineId,
                            request_id: String,
                            network_event: NetworkEvent) {

        let console_actor_name = match find_console_actor(actors.clone(), pipeline_id, None,
                                                          actor_workers, actor_pipelines) {
            Some(name) => name,
            None => return,
        };
        let netevent_actor_name = find_network_event_actor(actors.clone(), actor_requests, request_id.clone());
        let mut actors = actors.lock().unwrap();
        let actor = actors.find_mut::<NetworkEventActor>(&netevent_actor_name);

        match network_event {
            NetworkEvent::HttpRequest(url, method, headers, body) => {
                //Store the request information in the actor
                actor.add_request(url, method, headers, body);

                //Send a networkEvent message to the client
                let msg = NetworkEventMsg {
                    from: console_actor_name,
                    __type__: "networkEvent".to_string(),
                    eventActor: actor.event_actor(),
                };
                for stream in connections.iter_mut() {
                    stream.write_json_packet(&msg);
                }
            }
            NetworkEvent::HttpResponse(headers, status, body) => {
                //Store the response information in the actor
                actor.add_response(headers, status, body);

                //Send a networkEventUpdate (responseStart) to the client
                let msg = NetworkEventUpdateMsg {
                    from: netevent_actor_name,
                    __type__: "networkEventUpdate".to_string(),
                    updateType: "responseStart".to_string(),
                    response: actor.response_start()
                };

                for stream in connections.iter_mut() {
                    stream.write_json_packet(&msg);
                }
            }
            //TODO: Send the other types of update messages at appropriate times
            //      requestHeaders, requestCookies, responseHeaders, securityInfo, etc
        }
    }

    // Find the name of NetworkEventActor corresponding to request_id
    // Create a new one if it does not exist, add it to the actor_requests hashmap
    fn find_network_event_actor(actors: Arc<Mutex<ActorRegistry>>,
                                actor_requests: &mut HashMap<String, String>,
                                request_id: String) -> String {
        let mut actors = actors.lock().unwrap();
        match (*actor_requests).entry(request_id) {
            Occupied(name) => {
                //TODO: Delete from map like Firefox does?
                name.into_mut().clone()
            }
            Vacant(entry) => {
                let actor_name = actors.new_name("netevent");
                let actor = NetworkEventActor::new(actor_name.clone());
                entry.insert(actor_name.clone());
                actors.register(box actor);
                actor_name
            }
        }
    }

    let sender_clone = sender.clone();
    spawn_named("DevtoolsClientAcceptor".to_owned(), move || {
        // accept connections and process them, spawning a new task for each one
        for stream in listener.incoming() {
            // connection succeeded
            sender_clone.send(DevtoolsControlMsg::FromChrome(
                    ChromeToDevtoolsControlMsg::AddClient(stream.unwrap()))).unwrap();
        }
    });

    loop {
        match receiver.recv() {
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream))) => {
                let actors = actors.clone();
                accepted_connections.push(stream.try_clone().unwrap());
                spawn_named("DevtoolsClientHandler".to_owned(), move || {
                    handle_client(actors, stream.try_clone().unwrap())
                })
            }
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::FramerateTick(
                        actor_name, tick))) =>
                handle_framerate_tick(actors.clone(), actor_name, tick),
            Ok(DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal(
                        ids, script_sender, pageinfo))) =>
                handle_new_global(actors.clone(), ids, script_sender, sender.clone(), &mut actor_pipelines,
                                  &mut actor_workers, pageinfo),
            Ok(DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::SendConsoleMessage(
                        id,
                        console_message,
                        worker_id))) =>
                handle_console_message(actors.clone(), id, worker_id, console_message,
                                       &actor_pipelines, &actor_workers),
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEventMessage(
                        request_id, network_event))) => {
                // copy the accepted_connections vector
                let mut connections = Vec::<TcpStream>::new();
                for stream in accepted_connections.iter() {
                    connections.push(stream.try_clone().unwrap());
                }
                //TODO: Get pipeline_id from NetworkEventMessage after fixing the send in http_loader
                // For now, the id of the first pipeline is passed
                handle_network_event(actors.clone(), connections, &actor_pipelines, &mut actor_requests,
                                     &actor_workers, PipelineId(0), request_id, network_event);
            },
            Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg)) |
            Err(RecvError) => break
        }
    }
    for connection in accepted_connections.iter_mut() {
        let _ = connection.shutdown(Shutdown::Both);
    }
}
<|endoftext|>


<commit_before>use clippy_dev::clippy_project_root;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::io::ErrorKind;
use std::path::Path;

pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> Result<(), io::Error> {
    let pass = pass.expect("`pass` argument is validated by clap");
    let lint_name = lint_name.expect("`name` argument is validated by clap");
    let category = category.expect("`category` argument is validated by clap");

    match open_files(lint_name) {
        Ok((mut test_file, mut lint_file)) => {
            let (pass_type, pass_lifetimes, pass_import, context_import) = match pass {
                "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"),
                "late" => ("LateLintPass", "<'_, '_>", "use rustc_hir::*;", "LateContext"),
                _ => {
                    unreachable!("`pass_type` should only ever be `early` or `late`!");
                },
            };

            let camel_case_name = to_camel_case(lint_name);

            if let Err(e) = test_file.write_all(get_test_file_contents(lint_name).as_bytes()) {
                return Err(io::Error::new(
                    ErrorKind::Other,
                    format!("Could not write to test file: {}", e),
                ));
            };

            if let Err(e) = lint_file.write_all(
                get_lint_file_contents(
                    pass_type,
                    pass_lifetimes,
                    lint_name,
                    &camel_case_name,
                    category,
                    pass_import,
                    context_import,
                )
                .as_bytes(),
            ) {
                return Err(io::Error::new(
                    ErrorKind::Other,
                    format!("Could not write to lint file: {}", e),
                ));
            }
            Ok(())
        },
        Err(e) => Err(io::Error::new(
            ErrorKind::Other,
            format!("Unable to create lint: {}", e),
        )),
    }
}

fn open_files(lint_name: &str) -> Result<(File, File), io::Error> {
    let project_root = clippy_project_root();

    let test_file_path = project_root.join("tests").join("ui").join(format!("{}.rs", lint_name));
    let lint_file_path = project_root
        .join("clippy_lints")
        .join("src")
        .join(format!("{}.rs", lint_name));

    if Path::new(&test_file_path).exists() {
        return Err(io::Error::new(
            ErrorKind::AlreadyExists,
            format!("test file {:?} already exists", test_file_path),
        ));
    }
    if Path::new(&lint_file_path).exists() {
        return Err(io::Error::new(
            ErrorKind::AlreadyExists,
            format!("lint file {:?} already exists", lint_file_path),
        ));
    }

    let test_file = OpenOptions::new().write(true).create_new(true).open(test_file_path)?;
    let lint_file = OpenOptions::new().write(true).create_new(true).open(lint_file_path)?;

    Ok((test_file, lint_file))
}

fn to_camel_case(name: &str) -> String {
    name.split('_')
        .map(|s| {
            if s.is_empty() {
                String::from("")
            } else {
                [&s[0..1].to_uppercase(), &s[1..]].concat()
            }
        })
        .collect()
}

fn get_test_file_contents(lint_name: &str) -> String {
    format!(
        "#![warn(clippy::{})]

fn main() {{
    // test code goes here
}}
",
        lint_name
    )
}

fn get_lint_file_contents(
    pass_type: &str,
    pass_lifetimes: &str,
    lint_name: &str,
    camel_case_name: &str,
    category: &str,
    pass_import: &str,
    context_import: &str,
) -> String {
    format!(
        "use rustc_lint::{{{type}, {context_import}}};
use rustc_session::{{declare_lint_pass, declare_tool_lint}};
{pass_import}

declare_clippy_lint! {{
    /// **What it does:**
    ///
    /// **Why is this bad?**
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// // example code
    /// ```
    pub {name_upper},
    {category},
    \"default lint description\"
}}

declare_lint_pass!({name_camel} => [{name_upper}]);

impl {type}{lifetimes} for {name_camel} {{}}
",
        type=pass_type,
        lifetimes=pass_lifetimes,
        name_upper=lint_name.to_uppercase(),
        name_camel=camel_case_name,
        category=category,
        pass_import=pass_import,
        context_import=context_import
    )
}

#[test]
fn test_camel_case() {
    let s = "a_lint";
    let s2 = to_camel_case(s);
    assert_eq!(s2, "ALint");

    let name = "a_really_long_new_lint";
    let name2 = to_camel_case(name);
    assert_eq!(name2, "AReallyLongNewLint");

    let name3 = "lint__name";
    let name4 = to_camel_case(name3);
    assert_eq!(name4, "LintName");
}
<commit_msg>new_lint.rs: encourage authors to write more detailed code samples in lint descriptions (linted as well as fixed code)<commit_after>use clippy_dev::clippy_project_root;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::io::ErrorKind;
use std::path::Path;

pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> Result<(), io::Error> {
    let pass = pass.expect("`pass` argument is validated by clap");
    let lint_name = lint_name.expect("`name` argument is validated by clap");
    let category = category.expect("`category` argument is validated by clap");

    match open_files(lint_name) {
        Ok((mut test_file, mut lint_file)) => {
            let (pass_type, pass_lifetimes, pass_import, context_import) = match pass {
                "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"),
                "late" => ("LateLintPass", "<'_, '_>", "use rustc_hir::*;", "LateContext"),
                _ => {
                    unreachable!("`pass_type` should only ever be `early` or `late`!");
                },
            };

            let camel_case_name = to_camel_case(lint_name);

            if let Err(e) = test_file.write_all(get_test_file_contents(lint_name).as_bytes()) {
                return Err(io::Error::new(
                    ErrorKind::Other,
                    format!("Could not write to test file: {}", e),
                ));
            };

            if let Err(e) = lint_file.write_all(
                get_lint_file_contents(
                    pass_type,
                    pass_lifetimes,
                    lint_name,
                    &camel_case_name,
                    category,
                    pass_import,
                    context_import,
                )
                .as_bytes(),
            ) {
                return Err(io::Error::new(
                    ErrorKind::Other,
                    format!("Could not write to lint file: {}", e),
                ));
            }
            Ok(())
        },
        Err(e) => Err(io::Error::new(
            ErrorKind::Other,
            format!("Unable to create lint: {}", e),
        )),
    }
}

fn open_files(lint_name: &str) -> Result<(File, File), io::Error> {
    let project_root = clippy_project_root();

    let test_file_path = project_root.join("tests").join("ui").join(format!("{}.rs", lint_name));
    let lint_file_path = project_root
        .join("clippy_lints")
        .join("src")
        .join(format!("{}.rs", lint_name));

    if Path::new(&test_file_path).exists() {
        return Err(io::Error::new(
            ErrorKind::AlreadyExists,
            format!("test file {:?} already exists", test_file_path),
        ));
    }
    if Path::new(&lint_file_path).exists() {
        return Err(io::Error::new(
            ErrorKind::AlreadyExists,
            format!("lint file {:?} already exists", lint_file_path),
        ));
    }

    let test_file = OpenOptions::new().write(true).create_new(true).open(test_file_path)?;
    let lint_file = OpenOptions::new().write(true).create_new(true).open(lint_file_path)?;

    Ok((test_file, lint_file))
}

fn to_camel_case(name: &str) -> String {
    name.split('_')
        .map(|s| {
            if s.is_empty() {
                String::from("")
            } else {
                [&s[0..1].to_uppercase(), &s[1..]].concat()
            }
        })
        .collect()
}

fn get_test_file_contents(lint_name: &str) -> String {
    format!(
        "#![warn(clippy::{})]

fn main() {{
    // test code goes here
}}
",
        lint_name
    )
}

fn get_lint_file_contents(
    pass_type: &str,
    pass_lifetimes: &str,
    lint_name: &str,
    camel_case_name: &str,
    category: &str,
    pass_import: &str,
    context_import: &str,
) -> String {
    format!(
        "use rustc_lint::{{{type}, {context_import}}};
use rustc_session::{{declare_lint_pass, declare_tool_lint}};
{pass_import}

declare_clippy_lint! {{
    /// **What it does:**
    ///
    /// **Why is this bad?**
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// // example code where clippy issues a warning
    /// ```
    /// Use instead:
    /// ```rust
    /// // example code which does not raise clippy warning
    /// ```
    pub {name_upper},
    {category},
    \"default lint description\"
}}

declare_lint_pass!({name_camel} => [{name_upper}]);

impl {type}{lifetimes} for {name_camel} {{}}
",
        type=pass_type,
        lifetimes=pass_lifetimes,
        name_upper=lint_name.to_uppercase(),
        name_camel=camel_case_name,
        category=category,
        pass_import=pass_import,
        context_import=context_import
    )
}

#[test]
fn test_camel_case() {
    let s = "a_lint";
    let s2 = to_camel_case(s);
    assert_eq!(s2, "ALint");

    let name = "a_really_long_new_lint";
    let name2 = to_camel_case(name);
    assert_eq!(name2, "AReallyLongNewLint");

    let name3 = "lint__name";
    let name4 = to_camel_case(name3);
    assert_eq!(name4, "LintName");
}
<|endoftext|>


<commit_before>use rustc::hir::*;
use rustc::hir::map::Node::NodeItem;
use rustc::lint::*;
use rustc::ty::TypeVariants;
use syntax::ast::LitKind;
use syntax::symbol::InternedString;
use utils::paths;
use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty};

/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
///
/// **Why is this bad?** There is no point of doing that. `format!("too")` can
/// be replaced by `"foo".to_owned()` if you really need a `String`. The even
/// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
/// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
/// if `foo: &str`.
///
/// **Known problems:** None.
///
/// **Examples:**
/// ```rust
/// format!("foo")
/// format!("{}", foo)
/// ```
declare_lint! {
    pub USELESS_FORMAT,
    Warn,
    "useless use of `format!`"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array![USELESS_FORMAT]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let Some(span) = is_expn_of(expr.span, "format") {
            match expr.node {
                // `format!("{}", foo)` expansion
                ExprCall(ref fun, ref args) => {
                    if_let_chain!{[
                        let ExprPath(ref qpath) = fun.node,
                        args.len() == 2,
                        match_def_path(cx.tcx, resolve_node(cx, qpath, fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1),
                        // ensure the format string is `"{..}"` with only one argument and no text
                        check_static_str(cx, &args[0]),
                        // ensure the format argument is `{}` ie. Display with no fancy option
                        check_arg_is_display(cx, &args[1])
                    ], {
                        span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                    }}
                },
                // `format!("foo")` expansion contains `match () { () => [], }`
                ExprMatch(ref matchee, _, _) => {
                    if let ExprTup(ref tup) = matchee.node {
                        if tup.is_empty() {
                            span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                        }
                    }
                },
                _ => (),
            }
        }
    }
}

/// Returns the slice of format string parts in an `Arguments::new_v1` call.
/// Public because it's shared with a lint in print.rs.
pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Expr) -> Option<Vec<InternedString>> {
    if_let_chain! {[
        let ExprBlock(ref block) = expr.node,
        block.stmts.len() == 1,
        let StmtDecl(ref decl, _) = block.stmts[0].node,
        let DeclItem(ref decl) = decl.node,
        let Some(NodeItem(decl)) = cx.tcx.hir.find(decl.id),
        decl.name == "__STATIC_FMTSTR",
        let ItemStatic(_, _, ref expr) = decl.node,
        let ExprAddrOf(_, ref expr) = cx.tcx.hir.body(*expr).value.node, // &["…", "…", …]
        let ExprArray(ref exprs) = expr.node,
    ], {
        let mut result = Vec::new();
        for expr in exprs {
            if let ExprLit(ref lit) = expr.node {
                if let LitKind::Str(ref lit, _) = lit.node {
                    result.push(lit.as_str());
                }
            }
        }
        return Some(result);
    }}
    None
}

/// Checks if the expressions matches
/// ```rust
/// { static __STATIC_FMTSTR: … = &["…", "…", …]; __STATIC_FMTSTR }
/// ```
fn check_static_str(cx: &LateContext, expr: &Expr) -> bool {
    if let Some(expr) = get_argument_fmtstr_parts(cx, expr) {
        expr.len() == 1 && expr[0].is_empty()
    } else {
        false
    }
}

/// Checks if the expressions matches
/// ```rust
/// &match (&42,) {
///     (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)],
/// })
/// ```
fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
    if_let_chain! {[
        let ExprAddrOf(_, ref expr) = expr.node,
        let ExprMatch(_, ref arms, _) = expr.node,
        arms.len() == 1,
        arms[0].pats.len() == 1,
        let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node,
        pat.len() == 1,
        let ExprArray(ref exprs) = arms[0].body.node,
        exprs.len() == 1,
        let ExprCall(_, ref args) = exprs[0].node,
        args.len() == 2,
        let ExprPath(ref qpath) = args[1].node,
        match_def_path(cx.tcx, resolve_node(cx, qpath, args[1].id).def_id(), &paths::DISPLAY_FMT_METHOD),
    ], {
        let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));

        return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
    }}

    false
}
<commit_msg>Fix some doc errors<commit_after>use rustc::hir::*;
use rustc::hir::map::Node::NodeItem;
use rustc::lint::*;
use rustc::ty::TypeVariants;
use syntax::ast::LitKind;
use syntax::symbol::InternedString;
use utils::paths;
use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty};

/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
///
/// **Why is this bad?** There is no point of doing that. `format!("too")` can
/// be replaced by `"foo".to_owned()` if you really need a `String`. The even
/// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
/// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
/// if `foo: &str`.
///
/// **Known problems:** None.
///
/// **Examples:**
/// ```rust
/// format!("foo")
/// format!("{}", foo)
/// ```
declare_lint! {
    pub USELESS_FORMAT,
    Warn,
    "useless use of `format!`"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array![USELESS_FORMAT]
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let Some(span) = is_expn_of(expr.span, "format") {
            match expr.node {
                // `format!("{}", foo)` expansion
                ExprCall(ref fun, ref args) => {
                    if_let_chain!{[
                        let ExprPath(ref qpath) = fun.node,
                        args.len() == 2,
                        match_def_path(cx.tcx, resolve_node(cx, qpath, fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1),
                        // ensure the format string is `"{..}"` with only one argument and no text
                        check_static_str(cx, &args[0]),
                        // ensure the format argument is `{}` ie. Display with no fancy option
                        check_arg_is_display(cx, &args[1])
                    ], {
                        span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                    }}
                },
                // `format!("foo")` expansion contains `match () { () => [], }`
                ExprMatch(ref matchee, _, _) => {
                    if let ExprTup(ref tup) = matchee.node {
                        if tup.is_empty() {
                            span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                        }
                    }
                },
                _ => (),
            }
        }
    }
}

/// Returns the slice of format string parts in an `Arguments::new_v1` call.
/// Public because it's shared with a lint in print.rs.
pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Expr) -> Option<Vec<InternedString>> {
    if_let_chain! {[
        let ExprBlock(ref block) = expr.node,
        block.stmts.len() == 1,
        let StmtDecl(ref decl, _) = block.stmts[0].node,
        let DeclItem(ref decl) = decl.node,
        let Some(NodeItem(decl)) = cx.tcx.hir.find(decl.id),
        decl.name == "__STATIC_FMTSTR",
        let ItemStatic(_, _, ref expr) = decl.node,
        let ExprAddrOf(_, ref expr) = cx.tcx.hir.body(*expr).value.node, // &["…", "…", …]
        let ExprArray(ref exprs) = expr.node,
    ], {
        let mut result = Vec::new();
        for expr in exprs {
            if let ExprLit(ref lit) = expr.node {
                if let LitKind::Str(ref lit, _) = lit.node {
                    result.push(lit.as_str());
                }
            }
        }
        return Some(result);
    }}
    None
}

/// Checks if the expressions matches
/// ```rust
/// { static __STATIC_FMTSTR: s = &["a", "b", c]; __STATIC_FMTSTR }
/// ```
fn check_static_str(cx: &LateContext, expr: &Expr) -> bool {
    if let Some(expr) = get_argument_fmtstr_parts(cx, expr) {
        expr.len() == 1 && expr[0].is_empty()
    } else {
        false
    }
}

/// Checks if the expressions matches
/// ```rust,ignore
/// &match (&42,) {
///     (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)],
/// }
/// ```
fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
    if_let_chain! {[
        let ExprAddrOf(_, ref expr) = expr.node,
        let ExprMatch(_, ref arms, _) = expr.node,
        arms.len() == 1,
        arms[0].pats.len() == 1,
        let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node,
        pat.len() == 1,
        let ExprArray(ref exprs) = arms[0].body.node,
        exprs.len() == 1,
        let ExprCall(_, ref args) = exprs[0].node,
        args.len() == 2,
        let ExprPath(ref qpath) = args[1].node,
        match_def_path(cx.tcx, resolve_node(cx, qpath, args[1].id).def_id(), &paths::DISPLAY_FMT_METHOD),
    ], {
        let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));

        return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
    }}

    false
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate robots;

use std::any::Any;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender};
use std::time::Duration;

use robots::actors::{Actor, ActorSystem, ActorCell, ActorContext, ActorRef, Props};

#[derive(Debug, PartialEq)]
enum Res {
    Ok,
    Err,
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[derive(Copy, Clone)]
enum InternalStateMessage {
    Set(u32),
    Get,
    Panic,
}

struct InternalState {
    last: Mutex<u32>,
    sender: Arc<Mutex<Sender<Res>>>,
}

impl Actor for InternalState {
    fn receive(&self, message: Box<Any>, context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<InternalStateMessage>(message) {
            match *message {
                InternalStateMessage::Get => {
                    context.complete(context.sender(), *self.last.lock().unwrap())
                }
                InternalStateMessage::Set(message) => {
                    // Here mixing the test actor for the two tests might seem a bit weird,
                    // but we would get two very similar actors otherwise.
                    let mut last = self.last.lock().unwrap();
                    if message <= *last {
                        let _ = self.sender.lock().unwrap().send(Res::Err);
                    } else {
                        *last = message;
                    }
                    if *last == 1000 {
                        let _ = self.sender.lock().unwrap().send(Res::Ok);
                    }
                }
                InternalStateMessage::Panic => {
                    panic!("The actor panicked as it was asked to.")
                },
            }
        }
    }
}

impl InternalState {
    fn new(sender: Arc<Mutex<Sender<Res>>>) -> InternalState {
        InternalState {
            last: Mutex::new(0),
            sender: sender,
        }
    }
}

#[test]
fn read_messages_in_order() {
    let actor_system = ActorSystem::new("test".to_owned());
    actor_system.spawn_threads(9);

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(InternalState::new), tx);
    let actor_ref_1 = actor_system.actor_of(props.clone(), "sender".to_owned());
    let actor_ref_2 = actor_system.actor_of(props.clone(), "receiver".to_owned());

    for i in 1..1001 {
        actor_ref_1.tell_to(actor_ref_2.clone(), InternalStateMessage::Set(i as u32));
    }

    let res = rx.recv();
    assert_eq!(Ok(Res::Ok), res);

    actor_system.shutdown();
}

#[test]
fn recover_from_panic() {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, _rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(InternalState::new), tx);
    let requester = actor_system.actor_of(props.clone(), "sender".to_owned());
    let answerer = actor_system.actor_of(props.clone(), "receiver".to_owned());

    requester.tell_to(answerer.clone(), InternalStateMessage::Set(10));
    let res = actor_system.ask(answerer.clone(), InternalStateMessage::Get, "future_1".to_owned());
    let res: u32 = actor_system.extract_result(res);
    assert_eq!(10u32, res);

    requester.tell_to(answerer.clone(), InternalStateMessage::Panic);
    let res = actor_system.ask(answerer, InternalStateMessage::Get, "future_2".to_owned());
    let res: u32 = actor_system.extract_result(res);
    assert_eq!(0u32, res);

    actor_system.shutdown();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct Resolver;

impl Actor for Resolver {
    fn receive(&self, message: Box<Any>, context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<String>(message) {
            let future = context.identify_actor(*message, "resolver_request".to_owned());
            context.forward_result_to_future::<Option<ActorRef>>(future, context.sender());
        }
    }
}

impl Resolver {
    fn new(_dummy: ()) -> Resolver {
        Resolver
    }
}

#[test]
fn resolve_name_real_path() {
    let actor_system = ActorSystem::new("test".to_owned());

    let props = Props::new(Arc::new(Resolver::new), ());
    let answerer = actor_system.actor_of(props.clone(), "answerer".to_owned());
    let requester = actor_system.actor_of(props.clone(), "sender".to_owned());

    // We wait to be sure that the actors will be registered to the name resolver.
    std::thread::sleep(Duration::from_millis(100));

    let res = actor_system.ask(answerer, "/user/sender".to_owned(), "future".to_owned());
    println!("lol");
    let res: Option<ActorRef> = actor_system.extract_result(res);
    assert_eq!(requester.path(), res.unwrap().path());

    actor_system.shutdown();
}

#[test]
fn resolve_name_fake_path() {
    let actor_system = ActorSystem::new("test".to_owned());

    let props = Props::new(Arc::new(Resolver::new), ());
    let answerer = actor_system.actor_of(props.clone(), "answerer".to_owned());

    // We wait to be sure that the actors will be registered to the name resolver.
    std::thread::sleep(Duration::from_millis(100));

    let res = actor_system.ask(answerer, "/foo/bar".to_owned(), "future".to_owned());
    std::thread::sleep(Duration::from_millis(100));
    let res: Option<ActorRef> = actor_system.extract_result(res);

    match res {
        None => {}
        Some(_) => panic!("The name resolver gave an ActorRef when he should not."),
    };

    actor_system.shutdown();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct SimpleActor1 {
    sender: Arc<Mutex<Sender<Res>>>,
}

impl Actor for SimpleActor1 {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
        let _ = self.sender.lock().unwrap().send(Res::Ok);
    }
}

impl SimpleActor1 {
    fn new(sender: Arc<Mutex<Sender<Res>>>) -> SimpleActor1 {
        SimpleActor1 {
            sender: sender,
        }
    }
}

#[test]
fn receive_message () {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(SimpleActor1::new), tx);
    let actor_ref = actor_system.actor_of(props.clone(), "actor".to_owned());

    actor_system.tell(actor_ref, ());

    let res = rx.recv();
    assert_eq!(Ok(Res::Ok), res);

    actor_system.shutdown();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct SimpleActor2 {
    sender: Arc<Mutex<Sender<Res>>>,
    state: i32,
}

impl Actor for SimpleActor2 {
    fn receive(&self, message: Box<Any>, _context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<i32>(message) {
            if *message == self.state {
                let _ = self.sender.lock().unwrap().send(Res::Ok);
            } else {
                let _ = self.sender.lock().unwrap().send(Res::Err);
            }
        }
    }
}

impl SimpleActor2 {
    fn new(args: (Arc<Mutex<Sender<Res>>>, i32)) -> SimpleActor2 {
        SimpleActor2 {
            sender: args.0,
            state: args.1,
        }
    }
}

#[test]
fn receive_correct_message () {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));
    let value = 42;

    let props = Props::new(Arc::new(SimpleActor2::new), (tx, value));
    let actor_ref = actor_system.actor_of(props.clone(), "actor".to_owned());

    actor_system.tell(actor_ref, value);

    let res = rx.recv();
    assert_eq!(Ok(Res::Ok), res);

    actor_system.shutdown();
}

// This actor simply answers twice with () when send a message.
// He also sends () through a channel when restarted.
struct DoubleAnswer {
    sender: Arc<Mutex<Sender<()>>>,
}

impl Actor for DoubleAnswer {
    fn post_restart(&self, _context: ActorCell) {
        let mut sender = self.sender.lock().unwrap();
        sender.send(());
    }

    fn receive(&self, _message: Box<Any>, context: ActorCell) {
        context.tell(context.sender(), ());
        context.tell(context.sender(), ());
    }
}

impl DoubleAnswer {
    fn new(sender: Arc<Mutex<Sender<()>>>) -> DoubleAnswer {
        DoubleAnswer {
            sender: sender
        }
    }
}

#[test]
fn ask_answer_twice() {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(DoubleAnswer::new), tx);
    let answerer = actor_system.actor_of(props.clone(), "answerer".to_owned());

    let res = answerer.ask(()).await().unwrap();
    let res = *Box::<Any>::downcast::<()>(res).unwrap();
    // We chack that the value contained in the future is the correct one.
    assert_eq!(res, ());

    // We check that the actor has been restarted because of a panic (reason is not caught yet).
    let res = rx.recv();
    assert_eq!(res, Ok(()));

    std::thread::sleep(Duration::from_millis(10));

    actor_system.shutdown();
}
<commit_msg>Fix bad rebase<commit_after>extern crate env_logger;
extern crate robots;

use std::any::Any;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender};
use std::time::Duration;

use robots::actors::{Actor, ActorSystem, ActorCell, ActorContext, ActorRef, Props};

#[derive(Debug, PartialEq)]
enum Res {
    Ok,
    Err,
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[derive(Copy, Clone)]
enum InternalStateMessage {
    Set(u32),
    Get,
    Panic,
}

struct InternalState {
    last: Mutex<u32>,
    sender: Arc<Mutex<Sender<Res>>>,
}

impl Actor for InternalState {
    fn receive(&self, message: Box<Any>, context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<InternalStateMessage>(message) {
            match *message {
                InternalStateMessage::Get => {
                    context.complete(context.sender(), *self.last.lock().unwrap())
                }
                InternalStateMessage::Set(message) => {
                    // Here mixing the test actor for the two tests might seem a bit weird,
                    // but we would get two very similar actors otherwise.
                    let mut last = self.last.lock().unwrap();
                    if message <= *last {
                        let _ = self.sender.lock().unwrap().send(Res::Err);
                    } else {
                        *last = message;
                    }
                    if *last == 1000 {
                        let _ = self.sender.lock().unwrap().send(Res::Ok);
                    }
                }
                InternalStateMessage::Panic => {
                    panic!("The actor panicked as it was asked to.")
                },
            }
        }
    }
}

impl InternalState {
    fn new(sender: Arc<Mutex<Sender<Res>>>) -> InternalState {
        InternalState {
            last: Mutex::new(0),
            sender: sender,
        }
    }
}

#[test]
fn read_messages_in_order() {
    let actor_system = ActorSystem::new("test".to_owned());
    actor_system.spawn_threads(9);

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(InternalState::new), tx);
    let actor_ref_1 = actor_system.actor_of(props.clone(), "sender".to_owned());
    let actor_ref_2 = actor_system.actor_of(props.clone(), "receiver".to_owned());

    for i in 1..1001 {
        actor_ref_1.tell_to(actor_ref_2.clone(), InternalStateMessage::Set(i as u32));
    }

    let res = rx.recv();
    assert_eq!(Ok(Res::Ok), res);

    actor_system.shutdown();
}

#[test]
fn recover_from_panic() {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, _rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(InternalState::new), tx);
    let requester = actor_system.actor_of(props.clone(), "sender".to_owned());
    let answerer = actor_system.actor_of(props.clone(), "receiver".to_owned());

    requester.tell_to(answerer.clone(), InternalStateMessage::Set(10));
    let res = actor_system.ask(answerer.clone(), InternalStateMessage::Get, "future_1".to_owned());
    let res: u32 = actor_system.extract_result(res);
    assert_eq!(10u32, res);

    requester.tell_to(answerer.clone(), InternalStateMessage::Panic);
    let res = actor_system.ask(answerer, InternalStateMessage::Get, "future_2".to_owned());
    let res: u32 = actor_system.extract_result(res);
    assert_eq!(0u32, res);

    actor_system.shutdown();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct Resolver;

impl Actor for Resolver {
    fn receive(&self, message: Box<Any>, context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<String>(message) {
            let future = context.identify_actor(*message, "resolver_request".to_owned());
            context.forward_result_to_future::<Option<ActorRef>>(future, context.sender());
        }
    }
}

impl Resolver {
    fn new(_dummy: ()) -> Resolver {
        Resolver
    }
}

#[test]
fn resolve_name_real_path() {
    let actor_system = ActorSystem::new("test".to_owned());

    let props = Props::new(Arc::new(Resolver::new), ());
    let answerer = actor_system.actor_of(props.clone(), "answerer".to_owned());
    let requester = actor_system.actor_of(props.clone(), "sender".to_owned());

    // We wait to be sure that the actors will be registered to the name resolver.
    std::thread::sleep(Duration::from_millis(100));

    let res = actor_system.ask(answerer, "/user/sender".to_owned(), "future".to_owned());
    println!("lol");
    let res: Option<ActorRef> = actor_system.extract_result(res);
    assert_eq!(requester.path(), res.unwrap().path());

    actor_system.shutdown();
}

#[test]
fn resolve_name_fake_path() {
    let actor_system = ActorSystem::new("test".to_owned());

    let props = Props::new(Arc::new(Resolver::new), ());
    let answerer = actor_system.actor_of(props.clone(), "answerer".to_owned());

    // We wait to be sure that the actors will be registered to the name resolver.
    std::thread::sleep(Duration::from_millis(100));

    let res = actor_system.ask(answerer, "/foo/bar".to_owned(), "future".to_owned());
    std::thread::sleep(Duration::from_millis(100));
    let res: Option<ActorRef> = actor_system.extract_result(res);

    match res {
        None => {}
        Some(_) => panic!("The name resolver gave an ActorRef when he should not."),
    };

    actor_system.shutdown();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct SimpleActor1 {
    sender: Arc<Mutex<Sender<Res>>>,
}

impl Actor for SimpleActor1 {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
        let _ = self.sender.lock().unwrap().send(Res::Ok);
    }
}

impl SimpleActor1 {
    fn new(sender: Arc<Mutex<Sender<Res>>>) -> SimpleActor1 {
        SimpleActor1 {
            sender: sender,
        }
    }
}

#[test]
fn receive_message () {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));

    let props = Props::new(Arc::new(SimpleActor1::new), tx);
    let actor_ref = actor_system.actor_of(props.clone(), "actor".to_owned());

    actor_system.tell(actor_ref, ());

    let res = rx.recv();
    assert_eq!(Ok(Res::Ok), res);

    actor_system.shutdown();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct SimpleActor2 {
    sender: Arc<Mutex<Sender<Res>>>,
    state: i32,
}

impl Actor for SimpleActor2 {
    fn receive(&self, message: Box<Any>, _context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<i32>(message) {
            if *message == self.state {
                let _ = self.sender.lock().unwrap().send(Res::Ok);
            } else {
                let _ = self.sender.lock().unwrap().send(Res::Err);
            }
        }
    }
}

impl SimpleActor2 {
    fn new(args: (Arc<Mutex<Sender<Res>>>, i32)) -> SimpleActor2 {
        SimpleActor2 {
            sender: args.0,
            state: args.1,
        }
    }
}

#[test]
fn receive_correct_message () {
    let actor_system = ActorSystem::new("test".to_owned());

    let (tx, rx) = channel();
    let tx = Arc::new(Mutex::new(tx));
    let value = 42;

    let props = Props::new(Arc::new(SimpleActor2::new), (tx, value));
    let actor_ref = actor_system.actor_of(props.clone(), "actor".to_owned());

    actor_system.tell(actor_ref, value);

    let res = rx.recv();
    assert_eq!(Ok(Res::Ok), res);

    actor_system.shutdown();
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use std::thread;
use std::net::SocketAddr;
use std::net::TcpStream;
use std::sync::{Arc, Mutex, RwLock, mpsc};
use std::time::Duration;

use rocksdb::DB;

use super::cluster::{Simulator, Cluster};
use tikv::server::{Server, ServerTransport, SendCh, create_event_loop, Msg};
use tikv::server::{Node, Config};
use tikv::raftserver::Result;
use tikv::util::codec::rpc;
use tikv::storage::{Storage, Dsn};
use kvproto::raft_serverpb;
use kvproto::msgpb::{Message, MessageType};
use kvproto::raft_cmdpb::*;
use super::pd::TestPdClient;
use super::pd_ask::run_ask_loop;

pub struct ServerCluster {
    cluster_id: u64,
    senders: HashMap<u64, SendCh>,
    handles: HashMap<u64, thread::JoinHandle<()>>,
    addrs: HashMap<u64, SocketAddr>,
    conns: Mutex<HashMap<SocketAddr, Vec<TcpStream>>>,

    msg_id: Mutex<u64>,
    pd_client: Arc<RwLock<TestPdClient>>,
}

impl ServerCluster {
    pub fn new(cluster_id: u64, pd_client: Arc<RwLock<TestPdClient>>) -> ServerCluster {
        ServerCluster {
            cluster_id: cluster_id,
            senders: HashMap::new(),
            handles: HashMap::new(),
            addrs: HashMap::new(),
            conns: Mutex::new(HashMap::new()),
            msg_id: Mutex::new(0),
            pd_client: pd_client,
        }
    }

    fn alloc_msg_id(&self) -> u64 {
        let mut msg_id = self.msg_id.lock().unwrap();
        *msg_id += 1;
        *msg_id
    }

    fn get_conn(&self, addr: &SocketAddr) -> Result<TcpStream> {
        {
            let mut conns = self.conns
                                .lock()
                                .unwrap();
            let conn = conns.get_mut(addr);
            if let Some(mut pool) = conn {
                if !pool.is_empty() {
                    return Ok(pool.pop().unwrap());
                }
            }
        }

        let conn = TcpStream::connect(addr).unwrap();
        conn.set_nodelay(true).unwrap();
        Ok(conn)
    }
}

impl Simulator for ServerCluster {
    #[allow(useless_format)]
    fn run_node(&mut self, node_id: u64, cfg: Config, engine: Arc<DB>) -> u64 {
        assert!(node_id == 0 || !self.handles.contains_key(&node_id));
        assert!(node_id == 0 || !self.senders.contains_key(&node_id));

        let mut event_loop = create_event_loop().unwrap();
        let sendch = SendCh::new(event_loop.channel());
        let trans = Arc::new(RwLock::new(ServerTransport::new(self.cluster_id,
                                                              sendch,
                                                              self.pd_client.clone())));

        // TODO: we will create a Raft storage including Node and pass it to server later.
        // Now use a memory store instead.
        let mut cfg = cfg;
        let store = Storage::new(Dsn::Memory).unwrap();
        let mut server = Server::new(&mut event_loop, &cfg.addr, store, trans.clone()).unwrap();
        let addr = server.listening_addr().unwrap();

        cfg.addr = format!("{}", addr);

        let mut node = Node::new(&cfg, self.pd_client.clone(), trans);
        node.start(vec![engine]).unwrap();

        assert!(node_id == 0 || node_id == node.get_node_id());
        let node_id = node.get_node_id();

        let ch = server.get_sendch();

        let t = thread::spawn(move || {
            server.run(&mut event_loop).unwrap();

            // Force move node here, we will refactor whole later.
            drop(node)
        });

        self.handles.insert(node_id, t);
        self.senders.insert(node_id, ch);
        self.addrs.insert(node_id, addr);

        node_id
    }

    fn stop_node(&mut self, node_id: u64) {
        let h = self.handles.remove(&node_id).unwrap();
        let ch = self.senders.remove(&node_id).unwrap();
        self.addrs.remove(&node_id).unwrap();

        ch.send(Msg::Quit).unwrap();
        h.join().unwrap();
    }

    fn get_node_ids(&self) -> HashSet<u64> {
        self.senders.keys().cloned().collect()
    }

    fn call_command(&self, request: RaftCmdRequest, timeout: Duration) -> Result<RaftCmdResponse> {
        let node_id = request.get_header().get_peer().get_node_id();
        let addr = self.addrs.get(&node_id).unwrap();
        let mut conn = self.get_conn(addr).unwrap();

        let mut msg = Message::new();
        msg.set_msg_type(MessageType::Cmd);
        msg.set_cmd_req(request);

        let msg_id = self.alloc_msg_id();
        conn.set_write_timeout(Some(timeout)).unwrap();
        try!(rpc::encode_msg(&mut conn, msg_id, &msg));

        conn.set_read_timeout(Some(timeout)).unwrap();
        let mut resp_msg = Message::new();
        let get_msg_id = try!(rpc::decode_msg(&mut conn, &mut resp_msg));

        {
            let mut conns = self.conns
                                .lock()
                                .unwrap();
            let p = conns.entry(*addr).or_insert_with(Vec::new);
            p.push(conn);
        }

        assert_eq!(resp_msg.get_msg_type(), MessageType::CmdResp);
        assert_eq!(msg_id, get_msg_id);

        Ok(resp_msg.take_cmd_resp())
    }

    fn send_raft_msg(&self, raft_msg: raft_serverpb::RaftMessage) -> Result<()> {
        let node_id = raft_msg.get_to_peer().get_node_id();
        let addr = self.addrs.get(&node_id).unwrap();

        let mut conn = TcpStream::connect(addr).unwrap();
        conn.set_nodelay(true).unwrap();

        conn.set_write_timeout(Some(Duration::from_secs(3))).unwrap();

        let mut msg = Message::new();
        msg.set_msg_type(MessageType::Raft);
        msg.set_raft(raft_msg);

        let msg_id = self.alloc_msg_id();
        try!(rpc::encode_msg(&mut conn, msg_id, &msg));

        Ok(())
    }
}

pub fn new_server_cluster(id: u64, count: usize) -> Cluster<ServerCluster> {
    let (tx, rx) = mpsc::channel();
    let pd_client = Arc::new(RwLock::new(TestPdClient::new(tx)));
    let sim = Arc::new(RwLock::new(ServerCluster::new(id, pd_client.clone())));
    run_ask_loop(pd_client.clone(), sim.clone(), rx);
    Cluster::new(id, count, sim, pd_client)
}
<commit_msg>*: Introduce connection pool for send raft message.<commit_after>use std::collections::{HashMap, HashSet};
use std::thread;
use std::net::SocketAddr;
use std::net::TcpStream;
use std::sync::{Arc, Mutex, RwLock, mpsc};
use std::time::Duration;

use rocksdb::DB;

use super::cluster::{Simulator, Cluster};
use tikv::server::{Server, ServerTransport, SendCh, create_event_loop, Msg};
use tikv::server::{Node, Config};
use tikv::raftserver::Result;
use tikv::util::codec::rpc;
use tikv::storage::{Storage, Dsn};
use kvproto::raft_serverpb;
use kvproto::msgpb::{Message, MessageType};
use kvproto::raft_cmdpb::*;
use super::pd::TestPdClient;
use super::pd_ask::run_ask_loop;

pub struct ServerCluster {
    cluster_id: u64,
    senders: HashMap<u64, SendCh>,
    handles: HashMap<u64, thread::JoinHandle<()>>,
    addrs: HashMap<u64, SocketAddr>,
    conns: Mutex<HashMap<SocketAddr, Vec<TcpStream>>>,

    msg_id: Mutex<u64>,
    pd_client: Arc<RwLock<TestPdClient>>,
}

impl ServerCluster {
    pub fn new(cluster_id: u64, pd_client: Arc<RwLock<TestPdClient>>) -> ServerCluster {
        ServerCluster {
            cluster_id: cluster_id,
            senders: HashMap::new(),
            handles: HashMap::new(),
            addrs: HashMap::new(),
            conns: Mutex::new(HashMap::new()),
            msg_id: Mutex::new(0),
            pd_client: pd_client,
        }
    }

    fn alloc_msg_id(&self) -> u64 {
        let mut msg_id = self.msg_id.lock().unwrap();
        *msg_id += 1;
        *msg_id
    }

    fn pool_get(&self, addr: &SocketAddr) -> Result<TcpStream> {
        {
            let mut conns = self.conns
                                .lock()
                                .unwrap();
            let conn = conns.get_mut(addr);
            if let Some(mut pool) = conn {
                if !pool.is_empty() {
                    return Ok(pool.pop().unwrap());
                }
            }
        }

        let conn = TcpStream::connect(addr).unwrap();
        conn.set_nodelay(true).unwrap();
        Ok(conn)
    }

    fn pool_put(&self, addr: &SocketAddr, conn: TcpStream) {
        let mut conns = self.conns
                            .lock()
                            .unwrap();
        let p = conns.entry(*addr).or_insert_with(Vec::new);
        p.push(conn);
    }
}

impl Simulator for ServerCluster {
    #[allow(useless_format)]
    fn run_node(&mut self, node_id: u64, cfg: Config, engine: Arc<DB>) -> u64 {
        assert!(node_id == 0 || !self.handles.contains_key(&node_id));
        assert!(node_id == 0 || !self.senders.contains_key(&node_id));

        let mut event_loop = create_event_loop().unwrap();
        let sendch = SendCh::new(event_loop.channel());
        let trans = Arc::new(RwLock::new(ServerTransport::new(self.cluster_id,
                                                              sendch,
                                                              self.pd_client.clone())));

        // TODO: we will create a Raft storage including Node and pass it to server later.
        // Now use a memory store instead.
        let mut cfg = cfg;
        let store = Storage::new(Dsn::Memory).unwrap();
        let mut server = Server::new(&mut event_loop, &cfg.addr, store, trans.clone()).unwrap();
        let addr = server.listening_addr().unwrap();

        cfg.addr = format!("{}", addr);

        let mut node = Node::new(&cfg, self.pd_client.clone(), trans);
        node.start(vec![engine]).unwrap();

        assert!(node_id == 0 || node_id == node.get_node_id());
        let node_id = node.get_node_id();

        let ch = server.get_sendch();

        let t = thread::spawn(move || {
            server.run(&mut event_loop).unwrap();

            // Force move node here, we will refactor whole later.
            drop(node)
        });

        self.handles.insert(node_id, t);
        self.senders.insert(node_id, ch);
        self.addrs.insert(node_id, addr);

        node_id
    }

    fn stop_node(&mut self, node_id: u64) {
        let h = self.handles.remove(&node_id).unwrap();
        let ch = self.senders.remove(&node_id).unwrap();
        self.addrs.remove(&node_id).unwrap();

        ch.send(Msg::Quit).unwrap();
        h.join().unwrap();
    }

    fn get_node_ids(&self) -> HashSet<u64> {
        self.senders.keys().cloned().collect()
    }

    fn call_command(&self, request: RaftCmdRequest, timeout: Duration) -> Result<RaftCmdResponse> {
        let node_id = request.get_header().get_peer().get_node_id();
        let addr = self.addrs.get(&node_id).unwrap();
        let mut conn = self.pool_get(addr).unwrap();

        let mut msg = Message::new();
        msg.set_msg_type(MessageType::Cmd);
        msg.set_cmd_req(request);

        let msg_id = self.alloc_msg_id();
        conn.set_write_timeout(Some(timeout)).unwrap();
        try!(rpc::encode_msg(&mut conn, msg_id, &msg));

        conn.set_read_timeout(Some(timeout)).unwrap();
        let mut resp_msg = Message::new();
        let get_msg_id = try!(rpc::decode_msg(&mut conn, &mut resp_msg));

        self.pool_put(addr, conn);

        assert_eq!(resp_msg.get_msg_type(), MessageType::CmdResp);
        assert_eq!(msg_id, get_msg_id);

        Ok(resp_msg.take_cmd_resp())
    }

    fn send_raft_msg(&self, raft_msg: raft_serverpb::RaftMessage) -> Result<()> {
        let node_id = raft_msg.get_to_peer().get_node_id();
        let addr = self.addrs.get(&node_id).unwrap();

        let mut msg = Message::new();
        msg.set_msg_type(MessageType::Raft);
        msg.set_raft(raft_msg);
        let msg_id = self.alloc_msg_id();

        let mut conn = self.pool_get(addr).unwrap();
        conn.set_write_timeout(Some(Duration::from_secs(3))).unwrap();
        try!(rpc::encode_msg(&mut conn, msg_id, &msg));

        self.pool_put(addr, conn);

        Ok(())
    }
}

pub fn new_server_cluster(id: u64, count: usize) -> Cluster<ServerCluster> {
    let (tx, rx) = mpsc::channel();
    let pd_client = Arc::new(RwLock::new(TestPdClient::new(tx)));
    let sim = Arc::new(RwLock::new(ServerCluster::new(id, pd_client.clone())));
    run_ask_loop(pd_client.clone(), sim.clone(), rx);
    Cluster::new(id, count, sim, pd_client)
}
<|endoftext|>


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

use bv::BitSlice;
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};

use lz77;

#[derive(Debug)]
pub struct Colour {
    r: u8,
    g: u8,
    b: u8,
    a: u8,
}

#[derive(Debug)]
pub struct PivImage {
    palette: Vec<Colour>,
    pixels: Vec<usize>,
}

impl PivImage {
    pub fn from_file(filename: &String) -> Result<PivImage, io::Error> {
        let mut f = File::open(filename)?;
        let mut data: Vec<u8> = Vec::new();
        f.read_to_end(&mut data)?;
        let header = PivImage::read_header(&data[..6])?;

        let palette: Vec<Colour> =
            read_palette(header.bit_depth, &data[6..6 + (header.bit_depth * 2)])?;

        let extracted = lz77::decompress(header.file_length, &data[6 + (header.bit_depth * 2)..])?;
        let pixels = PivImage::combine_bit_planes(&extracted);
        Ok(PivImage {
            palette: palette,
            pixels: pixels,
        })
    }

    pub fn to_rgba8(&self) -> Vec<u8> {
        let width = 320;
        let height = 240;

        let mut pixels: Vec<u8> = Vec::with_capacity(width * height * 4);
        for pel in self.pixels.iter() {
            let colour = &self.palette[*pel];
            pixels.extend([colour.r, colour.g, colour.b, colour.a].iter())
        }
        pixels
    }

    fn read_header(data: &[u8]) -> Result<Header, io::Error> {
        let mut rdr = Cursor::new(data);
        let file_type = rdr.read_u16::<BigEndian>()?;
        rdr.seek(SeekFrom::Current(2))?;
        Ok(Header {
            file_length: rdr.read_u16::<BigEndian>()?,
            bit_depth: 1usize.wrapping_shl(file_type as u32),
        })
    }

    fn combine_bit_planes(data: &[u8]) -> Vec<usize> {
        let plane0 = BitSlice::from_slice(&data[..8000]);
        let plane1 = BitSlice::from_slice(&data[8000..16000]);
        let plane2 = BitSlice::from_slice(&data[16000..24000]);
        let plane3 = BitSlice::from_slice(&data[24000..32000]);
        let plane4 = BitSlice::from_slice(&data[32000..]);

        let mut pixels: Vec<usize> = Vec::with_capacity(64000);
        for i in (0..plane0.len()).map(|x| 7 - (x % 8) + x / 8 * 8) {
            let mut sum = 0;
            sum += plane0[i] as usize;
            sum += (plane1[i] as usize) << 1;
            sum += (plane2[i] as usize) << 2;
            sum += (plane3[i] as usize) << 3;
            sum += (plane4[i] as usize) << 4;

            pixels.push(sum);
        }
        pixels
    }
}

#[derive(Debug)]
struct Header {
    file_length: u16,
    bit_depth: usize,
}

pub fn read_palette(bit_depth: usize, data: &[u8]) -> Result<Vec<Colour>, io::Error> {
    let mut rdr = Cursor::new(data);
    let mut palette = vec![0; bit_depth];
    rdr.read_u16_into::<BigEndian>(&mut palette)?;
    let palette: Vec<u16> = palette.iter().map(|pel| pel & 0x7fff).collect();

    Ok(palette
        .iter()
        .map(|pel| {
            let mut pel_bytes = [0u8; 2];
            BigEndian::write_u16(&mut pel_bytes, *pel);
            let mut alpha = 0u8;
            if *pel != 0u16 {
                alpha = 255;
            }
            Colour {
                r: (pel_bytes[0]) << 4,
                g: (((pel_bytes[1]) & 0xf0) >> 2) << 2,
                b: ((pel_bytes[1]) & 0x0f) << 4,
                a: alpha,
            }
        })
        .collect())
}
<commit_msg>Rust: Don't use Cursor if not necessary<commit_after>use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::io::Cursor;

use bv::BitSlice;
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};

use lz77;

#[derive(Debug, Copy, Clone)]
pub struct Colour {
    r: u8,
    g: u8,
    b: u8,
    a: u8,
}

#[derive(Debug)]
pub struct PivImage {
    palette: Vec<Colour>,
    pixels: Vec<usize>,
}

impl PivImage {
    pub fn from_file(filename: &String) -> Result<PivImage, io::Error> {
        let mut f = File::open(filename)?;
        let mut data: Vec<u8> = Vec::new();
        f.read_to_end(&mut data)?;
        let header = PivImage::read_header(&data[..6]);

        let palette: Vec<Colour> =
            read_palette(header.bit_depth, &data[6..6 + (header.bit_depth * 2)]);

        let extracted = lz77::decompress(header.file_length, &data[6 + (header.bit_depth * 2)..])?;
        let pixels = PivImage::combine_bit_planes(&extracted);
        Ok(PivImage {
            palette: palette,
            pixels: pixels,
        })
    }

    pub fn to_rgba8(&self) -> Vec<u8> {
        let width = 320;
        let height = 240;

        let mut pixels: Vec<u8> = Vec::with_capacity(width * height * 4);
        for pel in self.pixels.iter() {
            let colour = &self.palette[*pel];
            pixels.extend([colour.r, colour.g, colour.b, colour.a].iter())
        }
        pixels
    }

    fn read_header(data: &[u8]) -> Header {
        let file_type = BigEndian::read_u16(&data[..2]);
        Header {
            file_length: BigEndian::read_u16(&data[4..6]),
            bit_depth: 1usize.wrapping_shl(file_type as u32),
        }
    }

    fn combine_bit_planes(data: &[u8]) -> Vec<usize> {
        let plane0 = BitSlice::from_slice(&data[..8000]);
        let plane1 = BitSlice::from_slice(&data[8000..16000]);
        let plane2 = BitSlice::from_slice(&data[16000..24000]);
        let plane3 = BitSlice::from_slice(&data[24000..32000]);
        let plane4 = BitSlice::from_slice(&data[32000..]);

        let mut pixels: Vec<usize> = Vec::with_capacity(64000);
        for i in (0..plane0.len()).map(|x| 7 - (x % 8) + x / 8 * 8) {
            let mut sum = 0;
            sum += plane0[i] as usize;
            sum += (plane1[i] as usize) << 1;
            sum += (plane2[i] as usize) << 2;
            sum += (plane3[i] as usize) << 3;
            sum += (plane4[i] as usize) << 4;

            pixels.push(sum);
        }
        pixels
    }
}

#[derive(Debug, Copy, Clone)]
struct Header {
    file_length: u16,
    bit_depth: usize,
}

pub fn read_palette(bit_depth: usize, data: &[u8]) -> Vec<Colour> {
    let mut palette = vec![0; bit_depth];
    BigEndian::read_u16_into(&data, &mut palette);
    let palette: Vec<u16> = palette.iter().map(|pel| pel & 0x7fff).collect();

    palette
        .iter()
        .map(|pel| {
            let mut pel_bytes = [0u8; 2];
            BigEndian::write_u16(&mut pel_bytes, *pel);
            let mut alpha = 0u8;
            if *pel != 0u16 {
                alpha = 255;
            }
            Colour {
                r: (pel_bytes[0]) << 4,
                g: (((pel_bytes[1]) & 0xf0) >> 2) << 2,
                b: ((pel_bytes[1]) & 0x0f) << 4,
                a: alpha,
            }
        })
        .collect()
}
<|endoftext|>