9 "github.com/anacrolix/missinggo"
11 "github.com/anacrolix/torrent/metainfo"
14 type pieceFileStorage struct {
15 fs missinggo.FileStore
18 func NewFileStorePieces(fs missinggo.FileStore) Client {
19 return &pieceFileStorage{
24 type pieceFileTorrentStorage struct {
28 func (s *pieceFileStorage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (Torrent, error) {
29 return &pieceFileTorrentStorage{s}, nil
32 func (s *pieceFileTorrentStorage) Close() error {
36 func (s *pieceFileTorrentStorage) Piece(p metainfo.Piece) Piece {
37 return pieceFileTorrentStoragePiece{s, p, s.s.fs}
40 type pieceFileTorrentStoragePiece struct {
41 ts *pieceFileTorrentStorage
43 fs missinggo.FileStore
46 func (s pieceFileTorrentStoragePiece) completedPath() string {
47 return path.Join("completed", s.p.Hash().HexString())
50 func (s pieceFileTorrentStoragePiece) incompletePath() string {
51 return path.Join("incomplete", s.p.Hash().HexString())
54 func (s pieceFileTorrentStoragePiece) GetIsComplete() bool {
55 fi, err := s.fs.Stat(s.completedPath())
56 return err == nil && fi.Size() == s.p.Length()
59 func (s pieceFileTorrentStoragePiece) MarkComplete() error {
60 return s.fs.Rename(s.incompletePath(), s.completedPath())
63 func (s pieceFileTorrentStoragePiece) openFile() (f missinggo.File, err error) {
64 f, err = s.fs.OpenFile(s.completedPath(), os.O_RDONLY)
68 if err == nil && fi.Size() == s.p.Length() {
72 } else if !os.IsNotExist(err) {
75 f, err = s.fs.OpenFile(s.incompletePath(), os.O_RDONLY)
76 if os.IsNotExist(err) {
77 err = io.ErrUnexpectedEOF
82 func (s pieceFileTorrentStoragePiece) ReadAt(b []byte, off int64) (n int, err error) {
83 f, err := s.openFile()
88 missinggo.LimitLen(&b, s.p.Length()-off)
89 n, err = f.ReadAt(b, off)
91 if off >= s.p.Length() {
93 } else if err == io.EOF {
94 err = io.ErrUnexpectedEOF
99 func (s pieceFileTorrentStoragePiece) WriteAt(b []byte, off int64) (n int, err error) {
100 if s.GetIsComplete() {
101 err = errors.New("piece completed")
104 f, err := s.fs.OpenFile(s.incompletePath(), os.O_WRONLY|os.O_CREATE)
109 missinggo.LimitLen(&b, s.p.Length()-off)
110 return f.WriteAt(b, off)