forked from cenkalti/rain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cachedpiece.go
53 lines (45 loc) 路 1.32 KB
/
cachedpiece.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package cachedpiece
import (
"encoding/binary"
"github.com/kyoto44/rain/piece"
"github.com/kyoto44/rain/piececache"
)
// CachedPiece is a wrapper around a piece.Piece object that is capable of reading the data from a picecache.Cache.
type CachedPiece struct {
pi *piece.Piece
cache *piececache.Cache
readSize int64
peerID []byte
}
// New returns a new CachedPiece object. Reads are done with blocks of `readSize`.
func New(pi *piece.Piece, cache *piececache.Cache, readSize int64, peerID [20]byte) *CachedPiece {
return &CachedPiece{
pi: pi,
cache: cache,
readSize: readSize,
peerID: peerID[:],
}
}
// ReadAt implements the io.ReaderAt interface.
func (c *CachedPiece) ReadAt(p []byte, off int64) (n int, err error) {
blk := uint32(off / c.readSize)
blkBegin := uint32(int64(blk) * c.readSize)
blkEnd := uint32(int64(blkBegin) + c.readSize)
if blkEnd > c.pi.Length {
blkEnd = c.pi.Length
}
key := make([]byte, 20+4+4)
copy(key, c.peerID)
binary.BigEndian.PutUint32(key[20:24], c.pi.Index)
binary.BigEndian.PutUint32(key[24:28], blk)
buf, err := c.cache.Get(string(key), func() ([]byte, error) {
b := make([]byte, blkEnd-blkBegin)
_, err = c.pi.Data.ReadAt(b, int64(blkBegin))
return b, err
})
if err != nil {
return
}
begin := off - int64(blkBegin)
return copy(p, buf[begin:]), nil
}