Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b65504f

Browse files
committedJan 25, 2024
fix: hold lock on torrent repo shard while reserving freed memory
1 parent 82a092f commit b65504f

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed
 

‎src/core/torrent/repositories.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::{HashSet, VecDeque};
22
use std::iter;
33
use std::mem::size_of;
4-
use std::sync::{Arc, Mutex};
4+
use std::sync::{Arc, Mutex, MutexGuard};
55

66
use dashmap::{DashMap, Map, SharedValue};
77

@@ -11,11 +11,10 @@ use crate::shared::bit_torrent::info_hash::InfoHash;
1111
use crate::shared::mem_size::{MemSize, POINTER_SIZE};
1212

1313
// todo: Make this a config option. Through env?
14-
const MAX_MEMORY_LIMIT: Option<usize> = Some(8_000_000_000); // 8GB
14+
const MAX_MEMORY_LIMIT: Option<usize> = Some(8_000); // 8GB
1515

1616
const INFO_HASH_SIZE: usize = size_of::<InfoHash>();
1717

18-
#[allow(dead_code)]
1918
/// Total memory impact of adding a new empty torrent ([torrent::Entry]) to a map.
2019
const TORRENT_INSERTION_SIZE_COST: usize = 216;
2120

@@ -326,6 +325,7 @@ impl RepositoryAsyncSingle {
326325
pub struct RepositoryDashmap {
327326
pub torrents: DashMap<InfoHash, Entry>,
328327
pub shard_priority_list: Vec<Mutex<VecDeque<InfoHash>>>,
328+
pub shard_locks: Vec<Mutex<()>>,
329329
}
330330

331331
impl MemSize for RepositoryDashmap {
@@ -387,6 +387,10 @@ impl RepositoryDashmap {
387387
index
388388
}
389389

390+
unsafe fn _yield_shard_lock(&self, shard_idx: usize) -> MutexGuard<'_, ()> {
391+
self.shard_locks.get_unchecked(shard_idx).lock().unwrap()
392+
}
393+
390394
fn check_do_free_memory_on_shard(&self, shard_idx: usize, amount: usize) {
391395
let mem_size_shard = self.get_shard_mem_size(shard_idx);
392396
let maybe_max_memory_available = MAX_MEMORY_LIMIT.map(|v| v / self.torrents._shard_count() - mem_size_shard);
@@ -460,16 +464,21 @@ impl Repository for RepositoryDashmap {
460464
.take(torrents._shard_count())
461465
.collect();
462466

467+
let shard_locks = iter::repeat_with(|| Mutex::new(())).take(torrents._shard_count()).collect();
468+
463469
Self {
464470
torrents,
465471
shard_priority_list,
472+
shard_locks,
466473
}
467474
}
468475

469476
fn upsert_torrent_with_peer_and_get_stats(&self, info_hash: &InfoHash, peer: &peer::Peer) -> (SwarmStats, bool) {
470477
let hash = self.torrents.hash_usize(&info_hash);
471478
let shard_idx = self.torrents.determine_shard(hash);
472479

480+
let _shard_lock = unsafe { self._yield_shard_lock(shard_idx) };
481+
473482
if !self.torrents.contains_key(info_hash) {
474483
self.check_do_free_memory_on_shard(shard_idx, TORRENT_INSERTION_SIZE_COST);
475484
self.insert_torrent_into_shard(shard_idx, info_hash);
@@ -492,6 +501,8 @@ impl Repository for RepositoryDashmap {
492501
let stats_updated = torrent.insert_or_update_peer(peer);
493502
let stats = torrent.get_stats();
494503

504+
drop(_shard_lock);
505+
495506
(
496507
SwarmStats {
497508
downloaded: stats.1,

0 commit comments

Comments
 (0)
Please sign in to comment.