8 "github.com/anacrolix/missinggo"
10 "github.com/anacrolix/torrent/metainfo"
13 type pieceFileStorage struct {
14 fs missinggo.FileStore
17 func NewFileStorePieces(fs missinggo.FileStore) ClientImpl {
18 return &pieceFileStorage{
23 type pieceFileTorrentStorage struct {
27 func (s *pieceFileStorage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (TorrentImpl, error) {
28 return &pieceFileTorrentStorage{s}, nil
31 func (s *pieceFileTorrentStorage) Close() error {
35 func (s *pieceFileTorrentStorage) Piece(p metainfo.Piece) PieceImpl {
36 return pieceFileTorrentStoragePiece{s, p, s.s.fs}
39 type pieceFileTorrentStoragePiece struct {
40 ts *pieceFileTorrentStorage
42 fs missinggo.FileStore
45 func (s pieceFileTorrentStoragePiece) completedPath() string {
46 return path.Join("completed", s.p.Hash().HexString())
49 func (s pieceFileTorrentStoragePiece) incompletePath() string {
50 return path.Join("incomplete", s.p.Hash().HexString())
53 func (s pieceFileTorrentStoragePiece) GetIsComplete() bool {
54 fi, err := s.fs.Stat(s.completedPath())
55 return err == nil && fi.Size() == s.p.Length()
58 func (s pieceFileTorrentStoragePiece) MarkComplete() error {
59 return s.fs.Rename(s.incompletePath(), s.completedPath())
62 func (s pieceFileTorrentStoragePiece) MarkNotComplete() error {
63 return s.fs.Remove(s.completedPath())
66 func (s pieceFileTorrentStoragePiece) openFile() (f missinggo.File, err error) {
67 f, err = s.fs.OpenFile(s.completedPath(), os.O_RDONLY)
71 if err == nil && fi.Size() == s.p.Length() {
75 } else if !os.IsNotExist(err) {
78 f, err = s.fs.OpenFile(s.incompletePath(), os.O_RDONLY)
79 if os.IsNotExist(err) {
80 err = io.ErrUnexpectedEOF
85 func (s pieceFileTorrentStoragePiece) ReadAt(b []byte, off int64) (n int, err error) {
86 f, err := s.openFile()
91 return f.ReadAt(b, off)
94 func (s pieceFileTorrentStoragePiece) WriteAt(b []byte, off int64) (n int, err error) {
95 f, err := s.fs.OpenFile(s.incompletePath(), os.O_WRONLY|os.O_CREATE)
100 return f.WriteAt(b, off)