storage/interface.go | 10 ++++++++-- torrent.go | 12 +++++++++++- diff --git a/storage/interface.go b/storage/interface.go index 869556f80a547265fad99ba61d919f77e57e59c1..584338cb4ae178d30ab1c04ee138981cb41f7071 100644 --- a/storage/interface.go +++ b/storage/interface.go @@ -22,8 +22,9 @@ Piece(metainfo.Piece) PieceImpl Close() error } -// Interacts with torrent piece data. Optional interfaces to implement include io.WriterTo, such as -// when a piece supports a more efficient way to write out incomplete chunks +// Interacts with torrent piece data. Optional interfaces to implement include: +// io.WriterTo, such as when a piece supports a more efficient way to write out incomplete chunks. +// SelfHashing, such as when a piece supports a more efficient way to hash its contents. type PieceImpl interface { // These interfaces are not as strict as normally required. They can // assume that the parameters are appropriate for the dimensions of the @@ -43,3 +44,8 @@ type Completion struct { Complete bool Ok bool } + +// Allows a storage backend to override hashing (i.e. if it can do it more efficiently than the torrent client can) +type SelfHashing interface { + SelfHash() (metainfo.Hash, error) +} diff --git a/torrent.go b/torrent.go index e38764742499d9db8fcd4b58b898cc9626d848aa..82b70c132cff0b25b58b10f3edc893d750d48b72 100644 --- a/torrent.go +++ b/torrent.go @@ -810,10 +810,20 @@ return pp.Integer(t.info.PieceLength) } func (t *Torrent) hashPiece(piece pieceIndex) (ret metainfo.Hash, err error) { - hash := pieceHash.New() p := t.piece(piece) p.waitNoPendingWrites() storagePiece := t.pieces[piece].Storage() + + //Does the backend want to do its own hashing? + if i, ok := storagePiece.PieceImpl.(storage.SelfHashing); ok { + var sum metainfo.Hash + //log.Printf("A piece decided to self-hash: %d", piece) + sum, err = i.SelfHash() + missinggo.CopyExact(&ret, sum) + return + } + + hash := pieceHash.New() const logPieceContents = false if logPieceContents { var examineBuf bytes.Buffer