Move from protobuf to bincode for a wire format

This commit migrates away from the `protobuf` crate to instead just working with
bincode on the wire as a serialization format. This is done by leveraging a few
different crates:

* The `bincode` and `serde_derive` crates are used to define serialization
  for Rust structures as well as provide a bincode implementation.
* The `tokio_io::codec::length_delimited` module implements framing via length
  prefixes to transform an asynchronous stream of bytes into a literal `Stream`
  of `BytesMut`.
* The `tokio_serde_bincode` crate is then used to tie it all together, parsing
  these `BytesMut` as the request/response types of sccache.

Most of the changes here are related to moving away from the protobuf API
throughout the codebase (e.g. `has_foo` and `take_foo`) towards a more
rustic-ish API that just uses enums/structs. Overall it felt quite natural (as
one would expect) to just use the raw enum/struct values.

This may not be quite as performant as before but that doesn't really apply to
sccache's use case where perf is hugely dominated by actually compiling and
hashing, so I'm not too too worried about that.

My personal motivation for this is twofold:

1. Using `protobuf` was a little clunky throughout the codebase and definitely
   had some sharp edges that felt good to smooth out.
2. There's currently what I believe some mysterious segfault and/or stray write
   happening in sccache and I'm not sure where. The `protobuf` crate had a lot
   of `unsafe` code and in lieu of actually auditing it I figured it'd be good
   to kill two birds with one stone. I have no idea if this fixes my segfault
   problem (I never could reproduce it) but I figured it's worth a shot.
This commit is contained in:
Alex Crichton 2017-03-22 10:21:52 -07:00
Родитель 76982eee57
Коммит a996ae6c2a
13 изменённых файлов: 379 добавлений и 3745 удалений

175
Cargo.lock сгенерированный
Просмотреть файл

@ -3,7 +3,8 @@ name = "sccache"
version = "0.1.1-pre"
dependencies = [
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0-alpha6 (git+https://github.com/TyOverby/bincode)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -13,8 +14,8 @@ dependencies = [
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.0-a.0 (git+https://github.com/alexcrichton/hyper?branch=tio)",
"hyper-tls 0.0.0 (git+https://github.com/alexcrichton/hyper-tls?branch=tio)",
"hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)",
"hyper-tls 0.0.0 (git+https://github.com/hyperium/hyper-tls)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -22,19 +23,21 @@ dependencies = [
"lru-disk-cache 0.1.0",
"mio-named-pipes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
"retry 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
"sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-process 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-serde-bincode 0.1.0 (git+https://github.com/alexcrichton/tokio-serde-bincode)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-uds 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -85,6 +88,16 @@ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bincode"
version = "1.0.0-alpha6"
source = "git+https://github.com/TyOverby/bincode#c971c4956d3719c62fa07e385b349428b94dddf7"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.5.0"
@ -173,7 +186,7 @@ dependencies = [
[[package]]
name = "dtoa"
version = "0.2.2"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -256,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.11.0-a.0"
source = "git+https://github.com/alexcrichton/hyper?branch=tio#0dcfd18e51b432f2b20a6345638577fc4256922c"
source = "git+https://github.com/hyperium/hyper#43cf9aefe8f9147a0f08aa0f9d609d275549fd7c"
dependencies = [
"base64 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -269,7 +282,7 @@ dependencies = [
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -279,13 +292,13 @@ dependencies = [
[[package]]
name = "hyper-tls"
version = "0.0.0"
source = "git+https://github.com/alexcrichton/hyper-tls?branch=tio#b696957381cca763acfcd0b97accef42001085b8"
source = "git+https://github.com/hyperium/hyper-tls#74aefbe500df5bb2d9a87844580b4ac21d49f134"
dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.0-a.0 (git+https://github.com/alexcrichton/hyper?branch=tio)",
"hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)",
"native-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -311,7 +324,7 @@ dependencies = [
[[package]]
name = "itoa"
version = "0.1.1"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -425,7 +438,7 @@ dependencies = [
[[package]]
name = "mio"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -446,7 +459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -457,7 +470,7 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -628,11 +641,6 @@ name = "podio"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "protobuf"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pulldown-cmark"
version = "0.0.3"
@ -641,6 +649,11 @@ dependencies = [
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.14"
@ -754,18 +767,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.8.0"
version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_json"
version = "0.8.1"
name = "serde_codegen_internals"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -806,6 +837,24 @@ name = "strsim"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "take"
version = "0.1.0"
@ -863,15 +912,15 @@ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-io"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -888,10 +937,10 @@ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-named-pipes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -909,10 +958,31 @@ dependencies = [
"smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-serde"
version = "0.1.0"
source = "git+https://github.com/carllerche/tokio-serde#fbafd2386d525d615332941d4e62c71af90dc40c"
dependencies = [
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-serde-bincode"
version = "0.1.0"
source = "git+https://github.com/alexcrichton/tokio-serde-bincode#31e64455a3e8ccedd08d240633dedf94a7eeb557"
dependencies = [
"bincode 1.0.0-alpha6 (git+https://github.com/TyOverby/bincode)",
"bytes 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-serde 0.1.0 (git+https://github.com/carllerche/tokio-serde)",
]
[[package]]
name = "tokio-service"
version = "0.1.0"
@ -929,7 +999,7 @@ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -943,7 +1013,7 @@ dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -956,10 +1026,10 @@ dependencies = [
"iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -993,6 +1063,11 @@ name = "unicode-width"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.4.0"
@ -1087,6 +1162,7 @@ dependencies = [
"checksum ansi_term 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30275ad0ad84ec1c06dde3b3f7d23c6006b7d76d61a85e7060b426b747eff70d"
"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4"
"checksum base64 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "065a0ce220ab84d0b6d5ae3e7bb77232209519c366f51f946fe28c19e84989d0"
"checksum bincode 1.0.0-alpha6 (git+https://github.com/TyOverby/bincode)" = "<none>"
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
@ -1098,7 +1174,7 @@ dependencies = [
"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
"checksum crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec"
"checksum daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0239832c1b4ca406d5ec73728cf4c7336d25cf85dd32db9e047e9e706ee0e935"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82dcb9ceed3868a03b335657b85a159736c961900f7e7747d3b0b97b9ccb5ccb"
"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
"checksum fern 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d2f58d053ad7791bfaad58a3f3541fe2d2aecc564dd82aee7f92fa402c054b2"
@ -1110,11 +1186,11 @@ dependencies = [
"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
"checksum hyper 0.11.0-a.0 (git+https://github.com/alexcrichton/hyper?branch=tio)" = "<none>"
"checksum hyper-tls 0.0.0 (git+https://github.com/alexcrichton/hyper-tls?branch=tio)" = "<none>"
"checksum hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)" = "<none>"
"checksum hyper-tls 0.0.0 (git+https://github.com/hyperium/hyper-tls)" = "<none>"
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
@ -1129,7 +1205,7 @@ dependencies = [
"checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151"
"checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66"
"checksum miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1f4d337a01c32e1f2122510fed46393d53ca35a7f429cb0450abaedfa3ed54"
"checksum mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aa30e3753079b08ce3d75cf3b44783e36fe0e1f64065f65c1d894d1688fb2580"
"checksum mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f27d38f824a0d267d55b29b171e9e99269a53812e385fa75c1fe700ae254a6a4"
"checksum mio-named-pipes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "82f43a815b57d2d652550f3d20cec88a495bb2d0956aa873dc43040278455677"
"checksum mio-uds 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c6a39bf21f6bf5cb2f07513c1e3519291db579386c34f8d1dd3b4f8565b53db8"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
@ -1150,8 +1226,8 @@ dependencies = [
"checksum openssl-sys 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b1482f9a06f56c906007e17ea14d73d102210b5d27bc948bf5e175f493f3f7c3"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
"checksum protobuf 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "0cf9bb92f38828ff1e0a7f828a0ec261ffdd5c9ef86b9b3bc7b1eef13495b563"
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
@ -1165,14 +1241,18 @@ dependencies = [
"checksum security-framework 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d7c1ff1c71e4e4474b46ded6687f0c28c721de2f5a05577e7f533d36330e4e3a"
"checksum security-framework-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5103c988054803538fe4d85333abf4c633f069510ab687dc71a50572104216d0"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad09a04412d1ac27ab9c1170190cfed637e0463f2f2ce79e718141624f43a45"
"checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc"
"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
"checksum serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d52006899f910528a10631e5b727973fe668f3228109d1707ccf5bad5490b6e"
"checksum serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f15ea24bd037b2d64646b4d934fa99c649be66e3f7b29fb595a5543b212b1452"
"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
"checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
"checksum skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24ebf8a06f5f8bae61ae5bbc7af7aac4ef6907ae975130faba1199e5fe82256a"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
"checksum strsim 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5f575d5ced6634a5c4cb842163dab907dc7e9148b28dc482d81b8855cbe985"
"checksum syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "480c834701caba3548aa991e54677281be3a5414a9d09ddbdf4ed74a569a9d19"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
"checksum tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0b62933a3f96cd559700662c34f8bab881d9e3540289fb4f368419c7f13a5aa9"
"checksum term_size 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a7c9a4de31e5622ec38533988a9e965aab09b26ee8bd7b8b0f56d488c3784d"
@ -1180,9 +1260,11 @@ dependencies = [
"checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
"checksum tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "99e958104a67877907c1454386d5482fe8e965a55d60be834a15a44328e7dc76"
"checksum tokio-io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a278fde45f1be68e44995227d426aaa4841e0980bb0a21b981092f28c3c8473"
"checksum tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "48f55df1341bb92281f229a6030bc2abffde2c7a44c6d6b802b7687dd8be0775"
"checksum tokio-process 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5414643999022a6efe54bc9ce03bae9db12694900208b4d3c56a18af71b8a4cb"
"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389"
"checksum tokio-serde 0.1.0 (git+https://github.com/carllerche/tokio-serde)" = "<none>"
"checksum tokio-serde-bincode 0.1.0 (git+https://github.com/alexcrichton/tokio-serde-bincode)" = "<none>"
"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
"checksum tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d121715f6917878a0df69f39365d01dd66c4463e4ba19efdcddcdfeb1bcb2bc"
"checksum tokio-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "666266622d9a4d1974a0beda33d505999515b0c60edc0c3fda09784e56609a97"
@ -1192,6 +1274,7 @@ dependencies = [
"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
"checksum unicode-width 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6722facc10989f63ee0e20a83cd4e1714a9ae11529403ac7e0afd069abc39e"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e"
"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"

Просмотреть файл

@ -9,7 +9,8 @@ repository = "https://github.com/mozilla/sccache/"
[dependencies]
app_dirs = "1.1.1"
bytes = "0.4"
bincode = { git = 'https://github.com/TyOverby/bincode' }
byteorder = "1.0"
chrono = "0.2.25"
clap = "2.3.0"
env_logger = "0.3.3"
@ -18,28 +19,30 @@ fern = "0.3.5"
filetime = "0.1"
futures = "0.1.11"
futures-cpupool = "0.1"
hyper = { git = "https://github.com/alexcrichton/hyper", branch = "tio" }
hyper-tls = { git = "https://github.com/alexcrichton/hyper-tls", branch = "tio" }
hyper = { git = "https://github.com/hyperium/hyper" }
hyper-tls = { git = "https://github.com/hyperium/hyper-tls" }
libc = "0.2.10"
local-encoding = "0.2.0"
log = "0.3.6"
lru-disk-cache = { path = "lru-disk-cache" }
number_prefix = "0.2.5"
protobuf = "1.0.18"
regex = "0.1.65"
retry = "0.4.0"
rust-crypto = "0.2.36"
rustc-serialize = "0.3"
serde_json = "0.8.0"
serde = "0.9"
serde_derive = "0.9"
serde_json = "0.9.0"
sha1 = "0.2.0"
tempdir = "0.3.4"
time = "0.1.35"
tokio-core = "0.1.6"
tokio-proto = "0.1"
tokio-io = "0.1"
tokio-process = "0.1"
tokio-proto = "0.1"
tokio-serde-bincode = { git = "https://github.com/alexcrichton/tokio-serde-bincode" }
tokio-service = "0.1"
tokio-tls = "0.1"
tokio-process = "0.1"
uuid = { version = "0.3.1", features = ["v4"] }
which = "0.2.1"
zip = { version = "0.2", default-features = false }

Просмотреть файл

@ -1,10 +0,0 @@
#!/bin/sh
#
# You must have protoc installed, as well as rust-protobuf installed and
# in your $PATH.
# On Ubuntu, `apt-get install protobuf-compiler` for protoc,
# and `cargo install protobuf` for rust-protobuf and follow the advice
# it outputs about $PATH.
d=$(dirname $0)
protoc --rust_out ${d}/src ${d}/protocol.proto

Просмотреть файл

@ -12,18 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use protobuf::{
CodedInputStream,
Message,
ProtobufError,
ProtobufResult,
parse_from_bytes,
};
use protocol::{
ClientRequest,
ServerResponse,
};
use byteorder::{ByteOrder, BigEndian};
use protocol::{Request, Response};
use retry::retry;
use bincode;
use errors::*;
use std::io::{
self,
BufReader,
@ -51,29 +44,30 @@ impl ServerConnection {
})
}
/// Send `request` to the server, read and return a `ServerResponse`.
pub fn request(&mut self, request : ClientRequest)
-> ProtobufResult<ServerResponse> {
/// Send `request` to the server, read and return a `Response`.
pub fn request(&mut self, request: Request) -> Result<Response> {
trace!("ServerConnection::request");
try!(request.write_length_delimited_to_writer(&mut self.writer));
try!(self.writer.flush().or_else(|e| Err(ProtobufError::IoError(e))));
let bytes = bincode::serialize(&request, bincode::Infinite)?;
let mut len = [0; 4];
BigEndian::write_u32(&mut len, bytes.len() as u32);
self.writer.write_all(&len)?;
self.writer.write_all(&bytes)?;
self.writer.flush()?;
trace!("ServerConnection::request: sent request");
self.read_one_response()
}
/// Read a single `ServerResponse` from the server.
pub fn read_one_response(&mut self) -> ProtobufResult<ServerResponse> {
/// Read a single `Response` from the server.
pub fn read_one_response(&mut self) -> Result<Response> {
trace!("ServerConnection::read_one_response");
//FIXME: wish `parse_length_delimited_from` worked here!
let len = try!({
let mut is = CodedInputStream::from_buffered_reader(&mut self.reader);
is.read_raw_varint32()
});
let mut bytes = [0; 4];
self.reader.read_exact(&mut bytes)?;
let len = BigEndian::read_u32(&bytes);
trace!("Should read {} more bytes", len);
let mut buf = vec![0; len as usize];
try!(self.reader.read_exact(&mut buf).or_else(|e| Err(ProtobufError::IoError(e))));
let mut data = vec![0; len as usize];
self.reader.read_exact(&mut data)?;
trace!("Done reading");
parse_from_bytes::<ServerResponse>(&buf)
Ok(bincode::deserialize(&data)?)
}
}

Просмотреть файл

@ -32,18 +32,8 @@ use number_prefix::{
Prefixed,
Standalone,
};
use protobuf::{RepeatedField, ProtobufError};
use protocol::{
CacheStats,
ClientRequest,
Compile,
CompileFinished,
CompileStarted,
GetStats,
Shutdown,
UnhandledCompile,
ZeroStats,
};
use protocol::{Request, Response, CacheStats, CompileResponse, CompileFinished};
use protocol::{Compile, CacheStat};
use server;
use std::env;
use std::ffi::{OsStr,OsString};
@ -69,14 +59,6 @@ pub const DEFAULT_PORT: u16 = 4226;
/// The number of milliseconds to wait for server startup.
const SERVER_STARTUP_TIMEOUT_MS: u32 = 5000;
/// Possible responses from the server for a `Compile` request.
enum CompileResponse {
/// The compilation was started.
CompileStarted(CompileStarted),
/// The server could not handle this compilation request.
UnhandledCompile(UnhandledCompile),
}
// Should this just be a Result?
/// Result of background server startup.
enum ServerStartup {
@ -384,14 +366,12 @@ fn connect_or_start_server(port: u16) -> Result<ServerConnection> {
/// Send a `ZeroStats` request to the server, and return the `CacheStats` request if successful.
pub fn request_zero_stats(mut conn : ServerConnection) -> Result<CacheStats> {
debug!("request_stats");
let mut req = ClientRequest::new();
req.set_zero_stats(ZeroStats::new());
//TODO: better error mapping
let mut response = conn.request(req).chain_err(|| {
let response = conn.request(Request::ZeroStats).chain_err(|| {
"failed to send zero statistics command to server or failed to receive respone"
})?;
if response.has_stats() {
Ok(response.take_stats())
if let Response::Stats(stats) = response {
Ok(stats)
} else {
bail!("Unexpected server response!")
}
@ -400,14 +380,12 @@ pub fn request_zero_stats(mut conn : ServerConnection) -> Result<CacheStats> {
/// Send a `GetStats` request to the server, and return the `CacheStats` request if successful.
pub fn request_stats(mut conn : ServerConnection) -> Result<CacheStats> {
debug!("request_stats");
let mut req = ClientRequest::new();
req.set_get_stats(GetStats::new());
//TODO: better error mapping
let mut response = conn.request(req).chain_err(|| {
let response = conn.request(Request::GetStats).chain_err(|| {
"Failed to send data to or receive data from server"
})?;
if response.has_stats() {
Ok(response.take_stats())
if let Response::Stats(stats) = response {
Ok(stats)
} else {
bail!("Unexpected server response!")
}
@ -416,14 +394,12 @@ pub fn request_stats(mut conn : ServerConnection) -> Result<CacheStats> {
/// Send a `Shutdown` request to the server, and return the `CacheStats` contained within the response if successful.
pub fn request_shutdown(mut conn : ServerConnection) -> Result<CacheStats> {
debug!("request_shutdown");
let mut req = ClientRequest::new();
req.set_shutdown(Shutdown::new());
//TODO: better error mapping
let mut response = conn.request(req).chain_err(|| {
let response = conn.request(Request::Shutdown).chain_err(|| {
"Failed to send data to or receive data from server"
})?;
if response.has_shutting_down() {
Ok(response.take_shutting_down().take_stats())
if let Response::ShuttingDown(stats) = response {
Ok(stats)
} else {
bail!("Unexpected server response!")
}
@ -431,21 +407,21 @@ pub fn request_shutdown(mut conn : ServerConnection) -> Result<CacheStats> {
/// Print `stats` to stdout.
fn print_stats(stats: CacheStats) -> Result<()> {
let formatted = stats.get_stats().iter()
.map(|s| (s.get_name(), if s.has_count() {
format!("{}", s.get_count())
} else if s.has_str() {
s.get_str().to_owned()
} else if s.has_size() {
match binary_prefix(s.get_size() as f64) {
Standalone(bytes) => format!("{} bytes", bytes),
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
}
} else {
String::from("???")
}))
let formatted = stats.stats.into_iter()
.map(|s| {
(s.name, match s.value {
CacheStat::Count(c) => c.to_string(),
CacheStat::String(s) => s,
CacheStat::Size(size) => {
match binary_prefix(size as f64) {
Standalone(bytes) => format!("{} bytes", bytes),
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
}
}
})
})
.collect::<Vec<_>>();
let name_width = formatted.iter().map(|&(n, _)| n.len()).max().unwrap();
let name_width = formatted.iter().map(|&(ref n, _)| n.len()).max().unwrap();
let stat_width = formatted.iter().map(|&(_, ref s)| s.len()).max().unwrap();
for (name, stat) in formatted {
println!("{:<name_width$} {:>stat_width$}", name, stat, name_width=name_width, stat_width=stat_width);
@ -455,28 +431,20 @@ fn print_stats(stats: CacheStats) -> Result<()> {
/// Send a `Compile` request to the server, and return the server response if successful.
fn request_compile<W: AsRef<Path>, X: AsRef<OsStr>, Y: AsRef<Path>>(conn: &mut ServerConnection, exe: W, args: &Vec<X>, cwd: Y) -> Result<CompileResponse> {
//TODO: It'd be nicer to send these over as raw bytes.
let exe = exe.as_ref().to_str().ok_or("bad exe")?;
let cwd = cwd.as_ref().to_str().ok_or("bad cwd")?;
let args = args.iter().filter_map(|a| a.as_ref().to_str().map(|s| s.to_owned())).collect::<Vec<_>>();
if args.is_empty() {
bail!("bad commandline")
}
let mut req = ClientRequest::new();
let mut compile = Compile::new();
compile.set_exe(exe.to_owned());
compile.set_cwd(cwd.to_owned());
compile.set_command(RepeatedField::from_vec(args));
trace!("request_compile: {:?}", compile);
req.set_compile(compile);
let req = Request::Compile(Compile {
exe: exe.as_ref().to_str().ok_or("bad exe")?.to_owned(),
cwd: cwd.as_ref().to_str().ok_or("bad cwd")?.to_owned(),
args: args.iter().map(|a| {
a.as_ref().to_str().ok_or("bad cwd".into()).map(|s| s.to_owned())
}).collect::<Result<_>>()?,
});
trace!("request_compile: {:?}", req);
//TODO: better error mapping?
let mut response = conn.request(req).chain_err(|| {
let response = conn.request(req).chain_err(|| {
"Failed to send data to or receive data from server"
})?;
if response.has_compile_started() {
Ok(CompileResponse::CompileStarted(response.take_compile_started()))
} else if response.has_unhandled_compile() {
Ok(CompileResponse::UnhandledCompile(response.take_unhandled_compile()))
if let Response::Compile(response) = response {
Ok(response)
} else {
bail!("Unexpected response from server")
}
@ -504,18 +472,14 @@ fn handle_compile_finished(response: CompileFinished,
// It might be nice if the server sent stdout/stderr as the process
// ran, but then it would have to also save them in the cache as
// interleaved streams to really make it work.
if response.has_stdout() {
try!(stdout.write_all(response.get_stdout()));
}
if response.has_stderr() {
try!(stderr.write_all(response.get_stderr()));
}
if response.has_retcode() {
let ret = response.get_retcode();
stdout.write_all(&response.stdout)?;
stderr.write_all(&response.stderr)?;
if let Some(ret) = response.retcode {
trace!("compiler exited with status {}", ret);
Ok(ret)
} else if response.has_signal() {
println!("Compiler killed by signal {}", response.get_signal());
} else if let Some(signal) = response.signal {
println!("Compiler killed by signal {}", signal);
Ok(-2)
} else {
println!("Missing compiler exit status!");
@ -542,39 +506,28 @@ fn handle_compile_response<T>(mut creator: T,
where T : CommandCreatorSync,
{
match response {
CompileResponse::CompileStarted(_) => {
CompileResponse::CompileStarted => {
debug!("Server sent CompileStarted");
// Wait for CompileFinished.
match conn.read_one_response() {
Ok(mut res) => {
if res.has_compile_finished() {
trace!("Server sent CompileFinished");
return handle_compile_finished(res.take_compile_finished(),
stdout, stderr)
} else {
bail!("unexpected response from server")
}
Ok(Response::CompileFinished(result)) => {
return handle_compile_finished(result, stdout, stderr)
}
// Currently the shutdown behavior of the remote sccache server
// is to wait at most N seconds for all active connections to
// finish and then close everything. If we get unlucky and don't
// get a response then we just forge ahead locally and run the
// compilation ourselves.
Err(ProtobufError::IoError(ref e))
if e.kind() == io::ErrorKind::UnexpectedEof => {
writeln!(io::stderr(),
"warning: sccache server looks like it shut down \
Ok(_) => bail!("unexpected response from server"),
Err(Error(ErrorKind::Io(ref e), _))
if e.kind() == io::ErrorKind::UnexpectedEof =>
{
writeln!(io::stderr(),
"warning: sccache server looks like it shut down \
unexpectedly, compiling locally instead").unwrap();
}
Err(e) => return Err(e).chain_err(|| {
Err(e) => return Err(e).chain_err(|| {
//TODO: something better here?
"error reading compile response from server"
})
}),
}
}
CompileResponse::UnhandledCompile(_) => {
CompileResponse::UnhandledCompile => {
debug!("Server sent UnhandledCompile");
}
};
@ -586,12 +539,12 @@ fn handle_compile_response<T>(mut creator: T,
if log_enabled!(Trace) {
trace!("running command: {:?}", cmd);
}
let output = try!(core.run(run_input_output(cmd, None)));
let output = core.run(run_input_output(cmd, None))?;
if !output.stdout.is_empty() {
try!(stdout.write_all(&output.stdout));
stdout.write_all(&output.stdout)?;
}
if !output.stderr.is_empty() {
try!(stderr.write_all(&output.stderr));
stderr.write_all(&output.stderr)?;
}
Ok(output.status.code().unwrap_or_else(|| {
if let Some(sig) = status_signal(output.status) {

Просмотреть файл

@ -16,16 +16,20 @@ use std::boxed::Box;
use std::error;
use std::io;
use bincode;
use futures::Future;
use futures::future;
use hyper;
use lru_disk_cache;
use serde_json;
error_chain! {
foreign_links {
Io(io::Error);
Hyper(hyper::Error);
Lru(lru_disk_cache::Error);
Json(serde_json::Error);
Bincode(bincode::Error);
}
errors {

Просмотреть файл

@ -13,7 +13,8 @@
// limitations under the License.
extern crate app_dirs;
extern crate bytes;
extern crate bincode;
extern crate byteorder;
extern crate chrono;
extern crate clap;
extern crate crypto;
@ -39,11 +40,12 @@ extern crate libc;
#[cfg(windows)]
extern crate mio_named_pipes;
extern crate number_prefix;
extern crate protobuf;
extern crate regex;
extern crate retry;
extern crate rustc_serialize;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate sha1;
extern crate tempdir;
extern crate time;
@ -52,6 +54,7 @@ extern crate tokio_io;
extern crate tokio_process;
extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_serde_bincode;
extern crate uuid;
#[cfg(windows)]
extern crate winapi;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use bytes::BytesMut;
use cache::{
Storage,
storage_from_environment,
@ -36,43 +35,27 @@ use mock_command::{
CommandCreatorSync,
ProcessCommandCreator,
};
use protobuf::{
self,
ProtobufError,
RepeatedField,
parse_length_delimited_from_bytes,
};
use protocol::{
ClientRequest,
CacheStats,
CacheStatistic,
Compile,
CompileFinished,
CompileStarted,
ServerResponse,
ShuttingDown,
UnhandledCompile,
UnknownCommand,
};
use std::collections::HashMap;
use protocol::{Compile, CompileFinished, CompileResponse};
use protocol::{Request, Response, CacheStats, CacheStat, CacheStatistic};
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::ffi::OsString;
use std::fs::metadata;
use std::io::{self, Write};
use std::marker;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::process::Output;
use std::process::{Output, ExitStatus};
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;
use tokio_core::reactor::{Handle, Core, Timeout};
use tokio_core::net::TcpListener;
use tokio_core::reactor::{Handle, Core, Timeout};
use tokio_io::codec::length_delimited::Framed;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Encoder, Decoder, Framed};
use tokio_proto::BindServer;
use tokio_proto::streaming::pipeline::{Frame, ServerProto, Transport};
use tokio_proto::streaming::{Body, Message};
use tokio_serde_bincode::{ReadBincode, WriteBincode};
use tokio_service::Service;
use util::fmt_duration_as_secs;
@ -325,8 +308,8 @@ struct SccacheService<C: CommandCreatorSync> {
info: ActiveInfo,
}
type SccacheRequest = Message<ClientRequest, Body<(), Error>>;
type SccacheResponse = Message<ServerResponse, Body<ServerResponse, Error>>;
type SccacheRequest = Message<Request, Body<(), Error>>;
type SccacheResponse = Message<Response, Body<Response, Error>>;
/// Messages sent from all services to the main event loop indicating activity.
///
@ -349,7 +332,6 @@ impl<C> Service for SccacheService<C>
type Future = SFuture<Self::Response>;
fn call(&self, req: Self::Request) -> Self::Future {
let mut req = req.into_inner();
trace!("handle_client");
// Opportunistically let channel know that we've received a request. We
@ -357,36 +339,32 @@ impl<C> Service for SccacheService<C>
// that every message is received.
drop(self.tx.clone().start_send(ServerMessage::Request));
if req.has_compile() {
debug!("handle_client: compile");
self.stats.borrow_mut().compile_requests += 1;
self.handle_compile(req.take_compile())
} else {
// Simple requests that can generate responses right away.
let mut res = ServerResponse::new();
if req.has_get_stats() {
let res = match req.into_inner() {
Request::Compile(compile) => {
debug!("handle_client: compile");
self.stats.borrow_mut().compile_requests += 1;
return self.handle_compile(compile)
}
Request::GetStats => {
debug!("handle_client: get_stats");
res.set_stats(self.get_stats());
} else if req.has_zero_stats() {
Response::Stats(self.get_stats())
}
Request::ZeroStats => {
debug!("handle_client: zero_stats");
res.set_stats(self.zero_stats());
} else if req.has_shutdown() {
Response::Stats(self.zero_stats())
}
Request::Shutdown => {
debug!("handle_client: shutdown");
let future = self.tx.clone().send(ServerMessage::Shutdown);
let me = self.clone();
return Box::new(future.then(move |_| {
let mut shutting_down = ShuttingDown::new();
shutting_down.set_stats(me.get_stats());
res.set_shutting_down(shutting_down);
Ok(Message::WithoutBody(res))
let stats = me.get_stats();
Ok(Message::WithoutBody(Response::ShuttingDown(stats)))
}))
} else {
warn!("handle_client: unknown command");
res.set_unknown(UnknownCommand::new());
}
};
f_ok(Message::WithoutBody(res))
}
f_ok(Message::WithoutBody(res))
}
}
@ -413,26 +391,26 @@ impl<C> SccacheService<C>
/// Get stats about the cache.
fn get_stats(&self) -> CacheStats {
let mut stats = CacheStats::new();
let mut stats_vec = self.stats.borrow().to_cache_statistics();
let mut stats = CacheStats {
stats: self.stats.borrow().to_cache_statistics(),
};
let mut stat = CacheStatistic::new();
stat.set_name(String::from("Cache location"));
stat.set_str(self.storage.location());
stats_vec.insert(0, stat);
stats.stats.push(CacheStatistic {
name: String::from("Cache location"),
value: CacheStat::String(self.storage.location()),
});
for &(s, v) in [("Cache size", self.storage.current_size()),
("Max cache size", self.storage.max_size())].iter() {
v.map(|val| {
let mut stat = CacheStatistic::new();
stat.set_name(String::from(s));
stat.set_size(val as u64);
stats_vec.insert(0, stat);
stats.stats.push(CacheStatistic {
name: String::from(s),
value: CacheStat::Size(val as u64),
});
});
}
stats.set_stats(RepeatedField::from_vec(stats_vec));
stats
return stats
}
/// Zero and return stats about the cache.
@ -447,12 +425,12 @@ impl<C> SccacheService<C>
/// This will handle a compile request entirely, generating a response with
/// the inital information and an optional body which will eventually
/// contain the results of the compilation.
fn handle_compile(&self, mut compile: Compile)
fn handle_compile(&self, compile: Compile)
-> SFuture<SccacheResponse>
{
let exe = compile.take_exe();
let cmd = compile.take_command().into_vec();
let cwd = compile.take_cwd();
let exe = compile.exe;
let cmd = compile.args;
let cwd = compile.cwd;
let me = self.clone();
Box::new(self.compiler_info(exe).map(move |info| {
me.check_compiler(info, cmd, cwd)
@ -504,7 +482,6 @@ impl<C> SccacheService<C>
cmd: Vec<String>,
cwd: String)
-> SccacheResponse {
let mut res = ServerResponse::new();
let mut stats = self.stats.borrow_mut();
match compiler {
None => {
@ -519,10 +496,10 @@ impl<C> SccacheService<C>
CompilerArguments::Ok(hasher) => {
debug!("parse_arguments: Ok");
stats.requests_executed += 1;
res.set_compile_started(CompileStarted::new());
let (tx, rx) = Body::pair();
self.start_compile_task(hasher, cmd, cwd, tx);
return Message::WithBody(res, rx)
let res = CompileResponse::CompileStarted;
return Message::WithBody(Response::Compile(res), rx)
}
CompilerArguments::CannotCache => {
debug!("parse_arguments: CannotCache");
@ -536,8 +513,8 @@ impl<C> SccacheService<C>
}
}
res.set_unhandled_compile(UnhandledCompile::new());
Message::WithoutBody(res)
let res = CompileResponse::UnhandledCompile;
Message::WithoutBody(Response::Compile(res))
}
/// Given compiler arguments `arguments`, look up
@ -547,7 +524,7 @@ impl<C> SccacheService<C>
hasher: Box<CompilerHasher<C>>,
arguments: Vec<String>,
cwd: String,
tx: mpsc::Sender<Result<ServerResponse>>) {
tx: mpsc::Sender<Result<Response>>) {
let cache_control = if self.force_recache {
CacheControl::ForceRecache
} else {
@ -563,10 +540,9 @@ impl<C> SccacheService<C>
self.handle.clone());
let me = self.clone();
let task = result.then(move |result| {
let mut res = ServerResponse::new();
let mut finish = CompileFinished::new();
let mut cache_write = None;
let mut stats = me.stats.borrow_mut();
let mut res = CompileFinished::default();
match result {
Ok((compiled, out)) => {
match compiled {
@ -603,13 +579,23 @@ impl<C> SccacheService<C>
}
};
let Output { status, stdout, stderr } = out;
status.code()
.map_or_else(
|| trace!("CompileFinished missing retcode"),
|s| { trace!("CompileFinished retcode: {}", s); finish.set_retcode(s) });
//TODO: sort out getting signal return on Unix
finish.set_stdout(stdout);
finish.set_stderr(stderr);
trace!("CompileFinished retcode: {}", status);
match status.code() {
Some(code) => res.retcode = Some(code),
None => res.signal = Some(get_signal(status)),
};
res.stdout = stdout;
res.stderr = stderr;
#[cfg(unix)]
fn get_signal(status: ExitStatus) -> i32 {
use std::os::unix::prelude::*;
status.signal().expect("must have signal")
}
#[cfg(windows)]
fn get_signal(_status: ExitStatus) -> i32 {
panic!("no signals on windows")
}
}
Err(err) => {
debug!("[{:?}] compilation failed: {:?}",
@ -620,11 +606,10 @@ impl<C> SccacheService<C>
}
stats.cache_errors += 1;
//TODO: figure out a better way to communicate this?
finish.set_retcode(-2);
res.retcode = Some(-2);
}
};
res.set_compile_finished(finish);
let send = tx.send(Ok(res));
let send = tx.send(Ok(Response::CompileFinished(res)));
let me = me.clone();
let cache_write = cache_write.then(move |result| {
@ -718,24 +703,25 @@ impl ServerStats {
fn to_cache_statistics(&self) -> Vec<CacheStatistic> {
macro_rules! set_stat {
($vec:ident, $var:expr, $name:expr) => {{
let mut stat = CacheStatistic::new();
stat.set_name(String::from($name));
stat.set_count($var);
$vec.push(stat);
$vec.push(CacheStatistic {
name: String::from($name),
value: CacheStat::Count($var),
});
}};
}
macro_rules! set_duration_stat {
($vec:ident, $dur:expr, $num:expr, $name:expr) => {{
let mut stat = CacheStatistic::new();
stat.set_name(String::from($name));
if $num > 0 {
let s = if $num > 0 {
let duration = $dur / $num as u32;
stat.set_str(fmt_duration_as_secs(&duration));
fmt_duration_as_secs(&duration)
} else {
stat.set_str("0.000s".to_owned());
}
$vec.push(stat);
"0.000s".to_owned()
};
$vec.push(CacheStatistic {
name: String::from($name),
value: CacheStat::String(s),
});
}};
}
@ -766,35 +752,48 @@ struct SccacheProto;
impl<I> ServerProto<I> for SccacheProto
where I: AsyncRead + AsyncWrite + 'static,
{
type Request = ClientRequest;
type Request = Request;
type RequestBody = ();
type Response = ServerResponse;
type ResponseBody = ServerResponse;
type Response = Response;
type ResponseBody = Response;
type Error = Error;
type Transport = SccacheTransport<I>;
type BindTransport = future::FutureResult<Self::Transport, io::Error>;
fn bind_transport(&self, io: I) -> Self::BindTransport {
future::ok(SccacheTransport {
inner: AsyncRead::framed(io, ProtobufCodec::new()),
inner: WriteBincode::new(ReadBincode::new(Framed::new(io))),
})
}
}
/// Implementation of `Stream + Sink` that tokio-proto is expecting. This takes
/// a `Framed` instance using `ProtobufCodec` and performs a simple map
/// operation on the sink/stream halves to translate the protobuf message types
/// to the `Frame` types that tokio-proto expects.
struct SccacheTransport<I> {
inner: Framed<I, ProtobufCodec<ClientRequest, ServerResponse>>,
/// Implementation of `Stream + Sink` that tokio-proto is expecting
///
/// This type is composed of a few layers:
///
/// * First there's `I`, the I/O object implementing `AsyncRead` and
/// `AsyncWrite`
/// * Next that's framed using the `length_delimited` module in tokio-io giving
/// us a `Sink` and `Stream` of `BytesMut`.
/// * Next that sink/stream is wrapped in `ReadBincode` which will cause the
/// `Stream` implementation to switch from `BytesMut` to `Request` by parsing
/// the bytes bincode.
/// * Finally that sink/stream is wrapped in `WriteBincode` which will cause the
/// `Sink` implementation to switch from `BytesMut` to `Response` meaning that
/// all `Response` types pushed in will be converted to `BytesMut` and pushed
/// below.
struct SccacheTransport<I: AsyncRead + AsyncWrite> {
inner: WriteBincode<ReadBincode<Framed<I>, Request>, Response>,
}
impl<I: AsyncRead + AsyncWrite> Stream for SccacheTransport<I> {
type Item = Frame<ClientRequest, (), Error>;
type Item = Frame<Request, (), Error>;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, io::Error> {
let msg = try_ready!(self.inner.poll());
let msg = try_ready!(self.inner.poll().map_err(|e| {
io::Error::new(io::ErrorKind::Other, e)
}));
Ok(msg.map(|m| {
Frame::Message {
message: m,
@ -805,7 +804,7 @@ impl<I: AsyncRead + AsyncWrite> Stream for SccacheTransport<I> {
}
impl<I: AsyncRead + AsyncWrite> Sink for SccacheTransport<I> {
type SinkItem = Frame<ServerResponse, ServerResponse, Error>;
type SinkItem = Frame<Response, Response, Error>;
type SinkError = io::Error;
fn start_send(&mut self, item: Self::SinkItem)
@ -854,73 +853,6 @@ impl<I: AsyncRead + AsyncWrite> Sink for SccacheTransport<I> {
impl<I: AsyncRead + AsyncWrite + 'static> Transport for SccacheTransport<I> {}
/// Simple tokio-core `Codec` which uses stock protobuf functions to
/// decode/encode protobuf messages.
struct ProtobufCodec<Request, Response> {
_marker: marker::PhantomData<fn() -> (Request, Response)>,
}
impl<Request, Response> ProtobufCodec<Request, Response>
where Request: protobuf::Message + protobuf::MessageStatic,
Response: protobuf::Message,
{
fn new() -> ProtobufCodec<Request, Response> {
ProtobufCodec { _marker: marker::PhantomData }
}
}
impl<Request, Response> Encoder for ProtobufCodec<Request, Response>
where Request: protobuf::Message + protobuf::MessageStatic,
Response: protobuf::Message,
{
type Item = Response;
type Error = io::Error;
fn encode(&mut self, msg: Response, buf: &mut BytesMut) -> io::Result<()> {
let bytes = msg.write_length_delimited_to_bytes().map_err(|e| {
io::Error::new(io::ErrorKind::Other, e)
})?;
buf.extend(&bytes);
Ok(())
}
}
impl<Request, Response> Decoder for ProtobufCodec<Request, Response>
where Request: protobuf::Message + protobuf::MessageStatic,
Response: protobuf::Message,
{
type Item = Request;
type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Request>> {
if buf.len() == 0 {
return Ok(None)
}
match parse_length_delimited_from_bytes::<Request>(&buf) {
Ok(req) => {
let size = req.write_length_delimited_to_bytes().unwrap().len();
buf.split_to(size);
Ok(Some(req))
}
// Unexpected EOF is OK, just means we haven't read enough
// bytes. It would be nice if this were discriminated more
// usefully.
// Issue filed: https://github.com/stepancheg/rust-protobuf/issues/154
Err(ProtobufError::WireError(s)) => {
if s == "truncated message" {
Ok(None)
} else {
Err(io::Error::new(io::ErrorKind::Other, s))
}
}
Err(ProtobufError::IoError(ioe)) => Err(ioe),
Err(ProtobufError::MessageNotInitialized { message }) => {
Err(io::Error::new(io::ErrorKind::Other, message))
}
}
}
}
struct ShutdownOrInactive {
rx: mpsc::Receiver<ServerMessage>,
handle: Handle,

Просмотреть файл

@ -355,19 +355,19 @@ impl ProvideAwsCredentials for IamProvider {
};
let access_key;
match json_object.find("AccessKeyId") {
match json_object.get("AccessKeyId") {
None => bail!("Couldn't find AccessKeyId in response."),
Some(val) => access_key = val.as_str().expect("AccessKeyId value was not a string").to_owned().replace("\"", "")
};
let secret_key;
match json_object.find("SecretAccessKey") {
match json_object.get("SecretAccessKey") {
None => bail!("Couldn't find SecretAccessKey in response."),
Some(val) => secret_key = val.as_str().expect("SecretAccessKey value was not a string").to_owned().replace("\"", "")
};
let expiration;
match json_object.find("Expiration") {
match json_object.get("Expiration") {
None => bail!("Couldn't find Expiration in response."),
Some(val) => expiration = val.as_str().expect("Expiration value was not a string").to_owned().replace("\"", "")
};
@ -377,7 +377,7 @@ impl ProvideAwsCredentials for IamProvider {
})?;
let token_from_response;
match json_object.find("Token") {
match json_object.get("Token") {
None => bail!("Couldn't find Token in response."),
Some(val) => token_from_response = val.as_str().expect("Token value was not a string").to_owned().replace("\"", "")
};

Просмотреть файл

@ -21,6 +21,7 @@ use commands::{
};
use env_logger;
use log::LogLevel::Trace;
use protocol::CacheStat;
use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr,OsString};

Просмотреть файл

@ -24,6 +24,7 @@ use ::commands::{
use env_logger;
use futures::sync::oneshot::{self, Sender};
use futures_cpupool::CpuPool;
use protocol::CacheStat;
use ::mock_command::*;
use ::server::{
ServerMessage,

Просмотреть файл

@ -15,14 +15,13 @@
#[cfg(unix)]
use libc;
use mock_command::*;
use protocol::CacheStats;
use protocol::{CacheStats, CacheStat};
use std::collections::HashMap;
use std::env;
use std::ffi::OsString;
use std::fs::{self,File};
use std::io;
use std::path::{Path,PathBuf};
use std::sync::{Arc,Mutex};
use tempdir::TempDir;
use tokio_core::reactor::Core;
@ -175,15 +174,8 @@ impl TestFixture {
}
}
#[derive(Debug, PartialEq)]
pub enum CacheStat {
Count(u64),
String(String),
Size(u64),
}
pub fn cache_stats_map(mut stats: CacheStats) -> HashMap<String, CacheStat> {
stats.take_stats().into_iter().map(|mut s| (s.take_name(), if s.has_count() { CacheStat::Count(s.get_count()) } else if s.has_size() { CacheStat::Size(s.get_size()) } else { CacheStat::String(s.take_str()) })).collect()
pub fn cache_stats_map(stats: CacheStats) -> HashMap<String, CacheStat> {
stats.stats.into_iter().map(|s| (s.name, s.value)).collect()
}
#[test]