|
- package cache
-
- import (
- "io"
- "time"
- )
-
- type RemoteLoader struct {
- file *CacheFile
- loaders []*OpenLoader
- }
-
- type OpenLoader struct {
- reader io.ReadCloser
- pos int64
- lastUsedTime time.Time
- }
-
- func newRemoteLoader(file *CacheFile) *RemoteLoader {
- return &RemoteLoader{
- file: file,
- loaders: make([]*OpenLoader, 2),
- }
- }
-
- func (r *RemoteLoader) Load(p []byte, pos int64) (n int, err error) {
- replaceIdx := -1
- for i := 0; i < len(r.loaders); i++ {
- loader := r.loaders[i]
- if loader == nil {
- replaceIdx = i
- continue
- }
-
- if loader.pos == pos {
- loader.lastUsedTime = time.Now()
- n, err = io.ReadFull(loader.reader, p)
- loader.pos += int64(n)
- if err != nil {
- loader.reader.Close()
- r.loaders[i] = nil
- }
- return
- }
-
- if replaceIdx == -1 || r.loaders[replaceIdx] != nil && r.loaders[replaceIdx].lastUsedTime.After(loader.lastUsedTime) {
- replaceIdx = i
- }
- }
-
- if r.loaders[replaceIdx] != nil {
- r.loaders[replaceIdx].reader.Close()
- r.loaders[replaceIdx] = nil
- }
-
- loader, err := r.newLoader(pos)
- if err != nil {
- return 0, err
- }
- loader.lastUsedTime = time.Now()
-
- r.loaders[replaceIdx] = loader
- n, err = io.ReadFull(loader.reader, p)
- loader.pos += int64(n)
- if err != nil {
- loader.reader.Close()
- r.loaders[replaceIdx] = nil
- }
- return
- }
-
- func (r *RemoteLoader) Close() {
- for i := 0; i < len(r.loaders); i++ {
- if r.loaders[i] != nil {
- r.loaders[i].reader.Close()
- }
- }
- }
-
- func (r *RemoteLoader) newLoader(pos int64) (*OpenLoader, error) {
- detail, err := r.file.cache.db.Object().GetDetail(r.file.cache.db.DefCtx(), r.file.remoteObj.ObjectID)
- if err != nil {
- return nil, err
- }
-
- down, err := r.file.cache.downloader.DownloadObjectByDetail(detail, pos, -1)
- if err != nil {
- return nil, err
- }
-
- return &OpenLoader{
- reader: down.File,
- pos: pos,
- }, nil
- }
|