Skip to content

Commit

Permalink
Merge #513: BEP 17. Persist metainfo field httpseeds
Browse files Browse the repository at this point in the history
d98c61a feat: [#438] persist metainfo field httpseeds. BEP 17 (Jose Celano)

Pull request description:

  The field `httpseeds` was included in the `Torrent` struct but not persisted into or loaded from database.

ACKs for top commit:
  josecelano:
    ACK d98c61a

Tree-SHA512: cf8e10aa288f7922134e47547dcd971460b5ba34bc865f782de6960f53604f3fe46211a8d9413b051cafa29d11208770bb1ab2a2b3ecad60d9ad3a09d3a3a530
  • Loading branch information
josecelano committed Mar 4, 2024
2 parents 11519b4 + d98c61a commit 1d54cdb
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS torrust_torrent_http_seeds (
http_seed_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
torrent_id INTEGER NOT NULL,
seed_url VARCHAR(256) NOT NULL,
FOREIGN KEY(torrent_id) REFERENCES torrust_torrents(torrent_id) ON DELETE CASCADE
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS torrust_torrent_http_seeds (
http_seed_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
torrent_id INTEGER NOT NULL,
seed_url TEXT NOT NULL,
FOREIGN KEY(torrent_id) REFERENCES torrust_torrents(torrent_id) ON DELETE CASCADE
)
21 changes: 19 additions & 2 deletions src/databases/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,14 @@ pub trait Database: Sync + Send {

let torrent_announce_urls = self.get_torrent_announce_urls_from_id(db_torrent.torrent_id).await?;

Ok(Torrent::from_database(&db_torrent, &torrent_files, torrent_announce_urls))
let torrent_http_seed_urls = self.get_torrent_http_seed_urls_from_id(db_torrent.torrent_id).await?;

Ok(Torrent::from_database(
&db_torrent,
&torrent_files,
torrent_announce_urls,
torrent_http_seed_urls,
))
}

/// Get `Torrent` from `torrent_id`.
Expand All @@ -217,7 +224,14 @@ pub trait Database: Sync + Send {

let torrent_announce_urls = self.get_torrent_announce_urls_from_id(torrent_id).await?;

Ok(Torrent::from_database(&db_torrent, &torrent_files, torrent_announce_urls))
let torrent_http_seed_urls = self.get_torrent_http_seed_urls_from_id(db_torrent.torrent_id).await?;

Ok(Torrent::from_database(
&db_torrent,
&torrent_files,
torrent_announce_urls,
torrent_http_seed_urls,
))
}

/// It returns the list of all infohashes producing the same canonical
Expand Down Expand Up @@ -257,6 +271,9 @@ pub trait Database: Sync + Send {
/// Get all torrent's announce urls as `Vec<Vec<String>>` from `torrent_id`.
async fn get_torrent_announce_urls_from_id(&self, torrent_id: i64) -> Result<Vec<Vec<String>>, Error>;

/// Get all torrent's HTTP seed urls as `Vec<Vec<String>>` from `torrent_id`.
async fn get_torrent_http_seed_urls_from_id(&self, torrent_id: i64) -> Result<Vec<String>, Error>;

/// Get `TorrentListing` from `torrent_id`.
async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, Error>;

Expand Down
37 changes: 35 additions & 2 deletions src/databases/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::models::category::CategoryId;
use crate::models::info_hash::InfoHash;
use crate::models::response::TorrentsResponse;
use crate::models::torrent::{Metadata, TorrentListing};
use crate::models::torrent_file::{DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, Torrent, TorrentFile};
use crate::models::torrent_file::{DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, DbTorrentHttpSeedUrl, Torrent, TorrentFile};
use crate::models::torrent_tag::{TagId, TorrentTag};
use crate::models::tracker_key::TrackerKey;
use crate::models::user::{User, UserAuthentication, UserCompact, UserId, UserProfile};
Expand Down Expand Up @@ -582,7 +582,31 @@ impl Database for Mysql {
return Err(e);
}

// Insert tags
// add HTTP seeds

let insert_torrent_http_seeds_result: Result<(), database::Error> = if let Some(http_seeds) = &torrent.httpseeds {
for seed_url in http_seeds {
let () = query("INSERT INTO torrust_torrent_http_seeds (torrent_id, seed_url) VALUES (?, ?)")
.bind(torrent_id)
.bind(seed_url)
.execute(&mut *tx)
.await
.map(|_| ())
.map_err(|_| database::Error::Error)?;
}

Ok(())
} else {
Ok(())
};

// rollback transaction on error
if let Err(e) = insert_torrent_http_seeds_result {
drop(tx.rollback().await);
return Err(e);
}

// add tags

for tag_id in &metadata.tags {
let insert_torrent_tag_result = query("INSERT INTO torrust_torrent_tag_links (torrent_id, tag_id) VALUES (?, ?)")
Expand Down Expand Up @@ -740,6 +764,15 @@ impl Database for Mysql {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_http_seed_urls_from_id(&self, torrent_id: i64) -> Result<Vec<String>, database::Error> {
query_as::<_, DbTorrentHttpSeedUrl>("SELECT seed_url FROM torrust_torrent_http_seeds WHERE torrent_id = ?")
.bind(torrent_id)
.fetch_all(&self.pool)
.await
.map(|v| v.iter().map(|a| a.seed_url.to_string()).collect())
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, database::Error> {
query_as::<_, TorrentListing>(
"SELECT
Expand Down
41 changes: 39 additions & 2 deletions src/databases/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::models::category::CategoryId;
use crate::models::info_hash::InfoHash;
use crate::models::response::TorrentsResponse;
use crate::models::torrent::{Metadata, TorrentListing};
use crate::models::torrent_file::{DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, Torrent, TorrentFile};
use crate::models::torrent_file::{DbTorrent, DbTorrentAnnounceUrl, DbTorrentFile, DbTorrentHttpSeedUrl, Torrent, TorrentFile};
use crate::models::torrent_tag::{TagId, TorrentTag};
use crate::models::tracker_key::TrackerKey;
use crate::models::user::{User, UserAuthentication, UserCompact, UserId, UserProfile};
Expand Down Expand Up @@ -504,6 +504,8 @@ impl Database for Sqlite {
return Err(e);
}

// add torrent files

let insert_torrent_files_result = if let Some(length) = torrent.info.length {
query("INSERT INTO torrust_torrent_files (md5sum, torrent_id, length) VALUES (?, ?, ?)")
.bind(torrent.info.md5sum.clone())
Expand Down Expand Up @@ -538,6 +540,8 @@ impl Database for Sqlite {
return Err(e);
}

// add announce URLs

let insert_torrent_announce_urls_result: Result<(), database::Error> = if let Some(announce_urls) = &torrent.announce_list
{
// flatten the nested vec (this will however remove the)
Expand Down Expand Up @@ -572,7 +576,31 @@ impl Database for Sqlite {
return Err(e);
}

// Insert tags
// add HTTP seeds

let insert_torrent_http_seeds_result: Result<(), database::Error> = if let Some(http_seeds) = &torrent.httpseeds {
for seed_url in http_seeds {
let () = query("INSERT INTO torrust_torrent_http_seeds (torrent_id, seed_url) VALUES (?, ?)")
.bind(torrent_id)
.bind(seed_url)
.execute(&mut *tx)
.await
.map(|_| ())
.map_err(|_| database::Error::Error)?;
}

Ok(())
} else {
Ok(())
};

// rollback transaction on error
if let Err(e) = insert_torrent_http_seeds_result {
drop(tx.rollback().await);
return Err(e);
}

// add tags

for tag_id in &metadata.tags {
let insert_torrent_tag_result = query("INSERT INTO torrust_torrent_tag_links (torrent_id, tag_id) VALUES (?, ?)")
Expand Down Expand Up @@ -730,6 +758,15 @@ impl Database for Sqlite {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_http_seed_urls_from_id(&self, torrent_id: i64) -> Result<Vec<String>, database::Error> {
query_as::<_, DbTorrentHttpSeedUrl>("SELECT seed_url FROM torrust_torrent_http_seeds WHERE torrent_id = ?")
.bind(torrent_id)
.fetch_all(&self.pool)
.await
.map(|v| v.iter().map(|a| a.seed_url.to_string()).collect())
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, database::Error> {
query_as::<_, TorrentListing>(
"SELECT
Expand Down
18 changes: 16 additions & 2 deletions src/models/torrent_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ impl Torrent {
/// This function will panic if the `torrent_info.pieces` is not a valid
/// hex string.
#[must_use]
pub fn from_database(db_torrent: &DbTorrent, torrent_files: &[TorrentFile], torrent_announce_urls: Vec<Vec<String>>) -> Self {
pub fn from_database(
db_torrent: &DbTorrent,
torrent_files: &[TorrentFile],
torrent_announce_urls: Vec<Vec<String>>,
torrent_http_seed_urls: Vec<String>,
) -> Self {
let info_dict = TorrentInfoDictionary::with(
&db_torrent.name,
db_torrent.piece_length,
Expand All @@ -85,7 +90,11 @@ impl Torrent {
announce: None,
nodes: None,
encoding: db_torrent.encoding.clone(),
httpseeds: None,
httpseeds: if torrent_http_seed_urls.is_empty() {
None
} else {
Some(torrent_http_seed_urls)
},
announce_list: Some(torrent_announce_urls),
creation_date: db_torrent.creation_date,
comment: db_torrent.comment.clone(),
Expand Down Expand Up @@ -345,6 +354,11 @@ pub struct DbTorrentAnnounceUrl {
pub tracker_url: String,
}

#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct DbTorrentHttpSeedUrl {
pub seed_url: String,
}

#[cfg(test)]
mod tests {

Expand Down

0 comments on commit 1d54cdb

Please sign in to comment.