diff --git a/src/accountsdb/download.zig b/src/accountsdb/download.zig index 24a848449..4838836b2 100644 --- a/src/accountsdb/download.zig +++ b/src/accountsdb/download.zig @@ -179,6 +179,7 @@ pub fn downloadSnapshotsFromGossip( output_dir: std.fs.Dir, min_mb_per_sec: usize, max_number_of_download_attempts: u64, + timeout: ?sig.time.Duration, ) !struct { std.fs.File, ?std.fs.File } { const logger = logger_.withScope(LOG_SCOPE); logger @@ -196,6 +197,7 @@ pub fn downloadSnapshotsFromGossip( var slow_peer_pubkeys = std.ArrayList(Pubkey).init(allocator); defer slow_peer_pubkeys.deinit(); + var function_duration = try std.time.Timer.start(); var download_attempts: u64 = 0; while (true) { std.time.sleep(5 * std.time.ns_per_s); // wait while gossip table updates @@ -205,6 +207,13 @@ pub fn downloadSnapshotsFromGossip( return error.UnableToDownloadSnapshot; } + if (timeout) |t| { + if (function_duration.read() > t.asNanos()) { + logger.err().logf("exceeded download timeout: {any}", .{t}); + return error.UnableToDownloadSnapshot; + } + } + // only hold gossip table lock for this block { const gossip_table, var gossip_table_lg = gossip_service.gossip_table_rw.readWithLock(); @@ -449,6 +458,7 @@ pub fn getOrDownloadAndUnpackSnapshot( min_snapshot_download_speed_mbs: usize = 20, trusted_validators: ?[]const Pubkey = null, max_number_of_download_attempts: u64 = default_adb_config.max_number_of_snapshot_download_attempts, + download_timeout: ?sig.time.Duration = null, }, ) !struct { FullAndIncrementalManifest, SnapshotFiles } { const logger = logger_.withScope(LOG_SCOPE); @@ -504,6 +514,7 @@ pub fn getOrDownloadAndUnpackSnapshot( snapshot_dir, @intCast(min_mb_per_sec), options.max_number_of_download_attempts, + options.download_timeout, ); defer full.close(); defer if (maybe_inc) |inc| inc.close(); diff --git a/src/benchmarks.zig b/src/benchmarks.zig index b18e989e4..3c72d8c7a 100644 --- a/src/benchmarks.zig +++ b/src/benchmarks.zig @@ -247,6 +247,7 @@ pub fn main() !void { .force_new_snapshot_download = true, .max_number_of_download_attempts = 50, .min_snapshot_download_speed_mbs = 10, + .download_timeout = Duration.fromMinutes(5), }, ) catch |err| { switch (err) { diff --git a/src/cmd/cmd.zig b/src/cmd/cmd.zig index 2f4058b60..d692c0a82 100644 --- a/src/cmd/cmd.zig +++ b/src/cmd/cmd.zig @@ -1554,6 +1554,7 @@ fn downloadSnapshot() !void { snapshot_dir, @intCast(min_mb_per_sec), config.current.accounts_db.max_number_of_snapshot_download_attempts, + null, ); defer full_file.close(); defer if (maybe_inc_file) |inc_file| inc_file.close(); diff --git a/src/time/time.zig b/src/time/time.zig index 4a89c46db..4594ee266 100644 --- a/src/time/time.zig +++ b/src/time/time.zig @@ -499,6 +499,10 @@ pub const Duration = struct { return .{ .ns = 0 }; } + pub fn fromMinutes(m: u64) Duration { + return .{ .ns = m * std.time.ns_per_min }; + } + pub fn fromSecs(s: u64) Duration { return .{ .ns = s * std.time.ns_per_s }; }