func (me *store) pieceComplete(p metainfo.Piece) bool { if me.completionKnown(p) { return me.isComplete(p) } // Prevent a errors from stalling the caller. if !me.lastError.IsZero() && time.Since(me.lastError) < time.Second { return false } length, err := me.db.GetLength(me.completedPiecePath(p)) if err == dataBackend.ErrNotFound { me.setCompletion(p, false) return false } if err != nil { me.lastError = time.Now() log.Printf("%+v", err) return false } complete := length == p.Length() if !complete { log.Printf("completed piece %x has wrong length: %d", p.Hash(), length) } me.setCompletion(p, complete) return complete }
func (me *store) path(p metainfo.Piece, completed bool) string { return filepath.Join(me.baseDir, func() string { if completed { return "complete" } else { return "incomplete" } }(), fmt.Sprintf("%x", p.Hash())) }
func (me *mapPieceCompletion) Set(p metainfo.Piece, b bool) error { if b { if me.m == nil { me.m = make(map[metainfo.PieceKey]struct{}) } me.m[p.Key()] = struct{}{} } else { delete(me.m, p.Key()) } return nil }
func (me *store) PieceCompleted(p metainfo.Piece) (err error) { hash, err := me.hashCopyFile(me.incompletePiecePath(p), me.completedPiecePath(p), p.Length()) if err == nil && !bytes.Equal(hash, p.Hash()) { err = errors.New("piece incomplete") } if err != nil { me.deleteCompleted(p) return } me.removePath(me.incompletePiecePath(p)) me.setCompletion(p, true) return }
func (me *store) PieceCompleted(p metainfo.Piece) (err error) { err = me.makeSpace(p.Length()) if err != nil { return } var ( incompletePiecePath = me.path(p, false) completedPiecePath = me.path(p, true) ) fSrc, err := os.Open(incompletePiecePath) if err != nil { return } defer fSrc.Close() os.MkdirAll(filepath.Dir(completedPiecePath), dirPerm) fDst, err := os.OpenFile(completedPiecePath, os.O_EXCL|os.O_CREATE|os.O_WRONLY, filePerm) if err != nil { return } defer fDst.Close() hasher := sha1.New() r := io.TeeReader(io.LimitReader(fSrc, p.Length()), hasher) _, err = io.Copy(fDst, r) if err != nil { return } if !bytes.Equal(hasher.Sum(nil), p.Hash()) { err = errors.New("piece incomplete") os.Remove(completedPiecePath) return } os.Remove(incompletePiecePath) me.completed[sliceToPieceHashArray(p.Hash())] = struct{}{} return }
func (s *piecePerResource) Piece(p metainfo.Piece) Piece { completed, err := s.p.NewInstance(path.Join("completed", p.Hash().HexString())) if err != nil { panic(err) } incomplete, err := s.p.NewInstance(path.Join("incomplete", p.Hash().HexString())) if err != nil { panic(err) } return piecePerResourcePiece{ p: p, c: completed, i: incomplete, } }
func (me *mmapTorrentStorage) Piece(p metainfo.Piece) Piece { return mmapStoragePiece{ storage: me, p: p, ReaderAt: io.NewSectionReader(me.span, p.Offset(), p.Length()), WriterAt: missinggo.NewSectionWriter(me.span, p.Offset(), p.Length()), } }
func (fts *fileTorrentStorage) Piece(p metainfo.Piece) Piece { // Create a view onto the file-based torrent storage. _io := fileStorageTorrent{fts} // Return the appropriate segments of this. return &fileStoragePiece{ fts, p, missinggo.NewSectionWriter(_io, p.Offset(), p.Length()), io.NewSectionReader(_io, p.Offset(), p.Length()), } }
func (me *fileStorage) Piece(p metainfo.Piece) Piece { _io := &fileStorageTorrent{ p.Info, me.baseDir, } return &fileStoragePiece{ me, p, missinggo.NewSectionWriter(_io, p.Offset(), p.Length()), io.NewSectionReader(_io, p.Offset(), p.Length()), } }
// Returns the file for the given piece, if it exists. It could be completed, // or incomplete. func (me *store) pieceRead(p metainfo.Piece) (f *os.File) { f, err := os.Open(me.path(p, true)) if err == nil { return } if !os.IsNotExist(err) { panic(err) } // Mark the file not completed, in case we thought it was. TODO: Trigger // an asynchronous initCompleted to reinitialize the entire completed map // as there are likely other files missing. me.mu.Lock() delete(me.completed, sliceToPieceHashArray(p.Hash())) me.mu.Unlock() f, err = os.Open(me.path(p, false)) if err == nil { return } if !os.IsNotExist(err) { panic(err) } return }
func (me *dbPieceCompletion) Get(p metainfo.Piece) (ret bool, err error) { row := me.db.QueryRow(`select exists(select * from completed where infohash=? and "index"=?)`, p.Info.Hash().HexString(), p.Index()) err = row.Scan(&ret) return }
func (me *data) pieceReader(p metainfo.Piece, off int64) (ret io.ReadCloser, err error) { return me.store.getPieceRange(p, off, p.Length()-off) }
func pieceHashArray(p metainfo.Piece) [20]byte { return sliceToPieceHashArray(p.Hash()) }
func (me *store) incompletePiecePath(p metainfo.Piece) string { return path.Join( "incomplete", strconv.FormatInt(int64(os.Getpid()), 10), hex.EncodeToString(p.Hash())) }
func (me *store) completedPiecePath(p metainfo.Piece) string { return path.Join("completed", hex.EncodeToString(p.Hash())) }
func (me *store) pieceComplete(p metainfo.Piece) bool { _, ok := me.completed[sliceToPieceHashArray(p.Hash())] return ok }
func (me *store) pieceComplete(p metainfo.Piece) bool { me.mu.Lock() defer me.mu.Unlock() _, ok := me.completed[sliceToPieceHashArray(p.Hash())] return ok }
func (me *dbPieceCompletion) Set(p metainfo.Piece, b bool) (err error) { if b { _, err = me.db.Exec(`insert into completed (infohash, "index") values (?, ?)`, p.Info.Hash().HexString(), p.Index()) } else { _, err = me.db.Exec(`delete from completed where infohash=? and "index"=?`, p.Info.Hash().HexString(), p.Index()) } return }
func (me *mapPieceCompletion) Get(p metainfo.Piece) (bool, error) { _, ok := me.m[p.Key()] return ok, nil }