Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
# If specified, wait this long for the server to start up.
server_startup_timeout_ms = 10000

# If specified, write JSON-formatted stats to this file after each compile operation.
cache_stats_file = "/home/user/.cache/sccache-stats.json"

[dist]
# where to find the scheduler
scheduler_url = "http://1.2.3.4:10600"
Expand Down
9 changes: 9 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ pub struct FileConfig {
pub cache: CacheConfigs,
pub dist: DistConfig,
pub server_startup_timeout_ms: Option<u64>,
pub cache_stats_file: Option<PathBuf>,
}

// If the file doesn't exist or we can't read it, log the issue and proceed. If the
Expand Down Expand Up @@ -978,6 +979,7 @@ pub struct Config {
pub fallback_cache: DiskCacheConfig,
pub dist: DistConfig,
pub server_startup_timeout: Option<std::time::Duration>,
pub cache_stats_file: Option<PathBuf>,
}

impl Config {
Expand All @@ -999,6 +1001,7 @@ impl Config {
cache,
dist,
server_startup_timeout_ms,
cache_stats_file,
} = file_conf;
conf_caches.merge(cache);

Expand All @@ -1014,6 +1017,7 @@ impl Config {
fallback_cache,
dist,
server_startup_timeout,
cache_stats_file,
}
}
}
Expand Down Expand Up @@ -1313,6 +1317,7 @@ fn config_overrides() {
},
dist: Default::default(),
server_startup_timeout_ms: None,
cache_stats_file: None,
};

assert_eq!(
Expand All @@ -1335,6 +1340,7 @@ fn config_overrides() {
},
dist: Default::default(),
server_startup_timeout: None,
cache_stats_file: None,
}
);
}
Expand Down Expand Up @@ -1484,6 +1490,7 @@ fn test_gcs_service_account() {
fn full_toml_parse() {
const CONFIG_STR: &str = r#"
server_startup_timeout_ms = 10000
cache_stats_file = "/home/user/.cache/sccache-stats.json"

[dist]
# where to find the scheduler
Expand Down Expand Up @@ -1644,6 +1651,7 @@ no_credentials = true
rewrite_includes_only: false,
},
server_startup_timeout_ms: Some(10000),
cache_stats_file: Some(PathBuf::from("/home/user/.cache/sccache-stats.json"))
}
)
}
Expand Down Expand Up @@ -1736,6 +1744,7 @@ size = "7g"
..Default::default()
},
server_startup_timeout_ms: None,
cache_stats_file: None,
}
);
}
77 changes: 67 additions & 10 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use anyhow::Context as _;
use bytes::{Bytes, BytesMut, buf::BufMut};
use filetime::FileTime;
use fs::metadata;
use fs::File;
use fs_err as fs;
use futures::channel::mpsc;
use futures::future::FutureExt;
Expand All @@ -42,15 +43,15 @@ use std::collections::{HashMap, HashSet};
use std::env;
use std::ffi::OsString;
use std::future::Future;
use std::io::{self, Write};
use std::io::{self, BufWriter, Write};
use std::marker::Unpin;
#[cfg(feature = "dist-client")]
use std::mem;
#[cfg(target_os = "android")]
use std::os::android::net::SocketAddrExt;
#[cfg(target_os = "linux")]
use std::os::linux::net::SocketAddrExt;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::process::{ExitStatus, Output};
use std::sync::Arc;
Expand Down Expand Up @@ -494,8 +495,14 @@ pub fn start_server(config: &Config, addr: &crate::net::SocketAddr) -> Result<()
crate::net::SocketAddr::Net(addr) => {
trace!("binding TCP {addr}");
let l = runtime.block_on(tokio::net::TcpListener::bind(addr))?;
let srv =
SccacheServer::<_>::with_listener(l, runtime, client, dist_client, storage);
let srv = SccacheServer::<_>::with_listener(
l,
runtime,
client,
dist_client,
storage,
config.cache_stats_file.clone(),
);
Ok((
srv.local_addr().unwrap(),
Box::new(move |f| srv.run(f)) as Box<dyn FnOnce(_) -> _>,
Expand All @@ -510,8 +517,14 @@ pub fn start_server(config: &Config, addr: &crate::net::SocketAddr) -> Result<()
let _guard = runtime.enter();
tokio::net::UnixListener::bind(path)?
};
let srv =
SccacheServer::<_>::with_listener(l, runtime, client, dist_client, storage);
let srv = SccacheServer::<_>::with_listener(
l,
runtime,
client,
dist_client,
storage,
config.cache_stats_file.clone(),
);
Ok((
srv.local_addr().unwrap(),
Box::new(move |f| srv.run(f)) as Box<dyn FnOnce(_) -> _>,
Expand All @@ -527,8 +540,14 @@ pub fn start_server(config: &Config, addr: &crate::net::SocketAddr) -> Result<()
let _guard = runtime.enter();
tokio::net::UnixListener::from_std(l)?
};
let srv =
SccacheServer::<_>::with_listener(l, runtime, client, dist_client, storage);
let srv = SccacheServer::<_>::with_listener(
l,
runtime,
client,
dist_client,
storage,
config.cache_stats_file.clone(),
);
Ok((
srv.local_addr()
.unwrap_or_else(|| crate::net::SocketAddr::UnixAbstract(p.to_vec())),
Expand Down Expand Up @@ -584,6 +603,7 @@ impl<C: CommandCreatorSync> SccacheServer<tokio::net::TcpListener, C> {
client: Client,
dist_client: DistClientContainer,
storage: Arc<dyn Storage>,
cache_stats_file: Option<PathBuf>,
) -> Result<Self> {
let addr = crate::net::SocketAddr::with_port(port);
let listener = runtime.block_on(tokio::net::TcpListener::bind(addr.as_net().unwrap()))?;
Expand All @@ -594,6 +614,7 @@ impl<C: CommandCreatorSync> SccacheServer<tokio::net::TcpListener, C> {
client,
dist_client,
storage,
cache_stats_file,
))
}
}
Expand All @@ -605,13 +626,22 @@ impl<A: crate::net::Acceptor, C: CommandCreatorSync> SccacheServer<A, C> {
client: Client,
dist_client: DistClientContainer,
storage: Arc<dyn Storage>,
cache_stats_file: Option<PathBuf>,
) -> Self {
// Prepare the service which we'll use to service all incoming TCP
// connections.
let (tx, rx) = mpsc::channel(1);
let (wait, info) = WaitUntilZero::new();
let pool = runtime.handle().clone();
let service = SccacheService::new(dist_client, storage, &client, pool, tx, info);
let service = SccacheService::new(
dist_client,
storage,
&client,
pool,
tx,
info,
cache_stats_file.clone(),
);

SccacheServer {
runtime,
Expand Down Expand Up @@ -823,6 +853,10 @@ where
/// This field causes [WaitUntilZero] to wait until this struct drops.
#[allow(dead_code)]
info: ActiveInfo,

/// A file that will contain JSON-formatted stats output, written after
/// each compile operation.
cache_stats_file: Option<PathBuf>,
}

type SccacheRequest = Message<Request, Body<()>>;
Expand Down Expand Up @@ -862,7 +896,11 @@ where
Request::Compile(compile) => {
debug!("handle_client: compile");
me.stats.lock().await.compile_requests += 1;
me.handle_compile(compile).await
let resp = me.handle_compile(compile).await;
if let Some(val) = &me.cache_stats_file {
me.stats.lock().await.clone().write(val)?
}
resp
}
Request::GetStats => {
debug!("handle_client: get_stats");
Expand Down Expand Up @@ -921,6 +959,7 @@ where
rt: tokio::runtime::Handle,
tx: mpsc::Sender<ServerMessage>,
info: ActiveInfo,
cache_stats_file: Option<PathBuf>,
) -> SccacheService<C> {
SccacheService {
stats: Arc::default(),
Expand All @@ -932,6 +971,7 @@ where
creator: C::new(client),
tx,
info,
cache_stats_file,
}
}

Expand All @@ -943,6 +983,7 @@ where
let (_, info) = WaitUntilZero::new();
let client = Client::new_num(1);
let dist_client = DistClientContainer::new_disabled();
let cache_stats_file = None;
SccacheService {
stats: Arc::default(),
dist_client: Arc::new(dist_client),
Expand All @@ -953,6 +994,7 @@ where
creator: C::new(&client),
tx,
info,
cache_stats_file,
}
}

Expand All @@ -965,6 +1007,7 @@ where
let (tx, _) = mpsc::channel(1);
let (_, info) = WaitUntilZero::new();
let client = Client::new_num(1);
let cache_stats_file = None;
SccacheService {
stats: Arc::default(),
dist_client: Arc::new(DistClientContainer::new_with_state(DistClientState::Some(
Expand All @@ -986,6 +1029,7 @@ where
creator: C::new(&client),
tx,
info,
cache_stats_file,
}
}

Expand Down Expand Up @@ -1910,6 +1954,19 @@ impl ServerStats {
);
}
}

/// Write stats in JSON format to a file.
fn write(&self, path: &Path) -> Result<()> {
let file = match File::create(path) {
Ok(f) => f,
Err(e) => {
debug!("Couldn't open stats file for writing: {}", e);
return Ok(());
}
};
let mut writer = BufWriter::new(file);
Ok(serde_json::to_writer(&mut writer, self)?)
}
}

fn set_percentage_stat(
Expand Down
2 changes: 1 addition & 1 deletion src/test/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ where
));

let client = Client::new();
let srv = SccacheServer::new(0, runtime, client, dist_client, storage).unwrap();
let srv = SccacheServer::new(0, runtime, client, dist_client, storage, None).unwrap();
let mut srv: SccacheServer<_, Arc<Mutex<MockCommandCreator>>> = srv;
let addr = srv.local_addr().unwrap();
assert!(matches!(addr, crate::net::SocketAddr::Net(a) if a.port() > 0));
Expand Down
1 change: 1 addition & 0 deletions tests/harness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ pub fn sccache_client_cfg(
rewrite_includes_only: false, // TODO
},
server_startup_timeout_ms: None,
cache_stats_file: None,
}
}

Expand Down
1 change: 1 addition & 0 deletions tests/oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ fn config_with_dist_auth(
rewrite_includes_only: true,
},
server_startup_timeout_ms: None,
cache_stats_file: None,
}
}

Expand Down
Loading