github.com/uber/kraken@v0.1.4/lib/torrent/storage/originstorage/torrent_archive.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package originstorage 15 16 import ( 17 "errors" 18 "fmt" 19 "os" 20 21 "github.com/uber/kraken/core" 22 "github.com/uber/kraken/lib/blobrefresh" 23 "github.com/uber/kraken/lib/store" 24 "github.com/uber/kraken/lib/store/metadata" 25 "github.com/uber/kraken/lib/torrent/storage" 26 27 "github.com/willf/bitset" 28 ) 29 30 // TorrentArchive is a TorrentArchive for origin peers. It assumes that 31 // all files (including metainfo) are already downloaded and in the cache directory. 32 type TorrentArchive struct { 33 cas *store.CAStore 34 blobRefresher *blobrefresh.Refresher 35 } 36 37 // NewTorrentArchive creates a new TorrentArchive. 38 func NewTorrentArchive( 39 cas *store.CAStore, blobRefresher *blobrefresh.Refresher) *TorrentArchive { 40 41 return &TorrentArchive{cas, blobRefresher} 42 } 43 44 func (a *TorrentArchive) getMetaInfo(namespace string, d core.Digest) (*core.MetaInfo, error) { 45 var tm metadata.TorrentMeta 46 if err := a.cas.GetCacheFileMetadata(d.Hex(), &tm); err != nil { 47 if os.IsNotExist(err) { 48 refreshErr := a.blobRefresher.Refresh(namespace, d) 49 if refreshErr != nil { 50 return nil, fmt.Errorf("blob refresh: %s", refreshErr) 51 } 52 return nil, errors.New("refreshing blob") 53 } 54 return nil, err 55 } 56 return tm.MetaInfo, nil 57 } 58 59 // Stat returns TorrentInfo for given digest. If the file does not exist, 60 // attempts to re-fetch the file from the storae backend configured for namespace 61 // in a background goroutine. 62 func (a *TorrentArchive) Stat(namespace string, d core.Digest) (*storage.TorrentInfo, error) { 63 mi, err := a.getMetaInfo(namespace, d) 64 if err != nil { 65 return nil, err 66 } 67 bitfield := bitset.New(uint(mi.NumPieces())).Complement() 68 return storage.NewTorrentInfo(mi, bitfield), nil 69 } 70 71 // CreateTorrent is not supported. 72 func (a *TorrentArchive) CreateTorrent(namespace string, d core.Digest) (storage.Torrent, error) { 73 return nil, errors.New("not supported for origin") 74 } 75 76 // GetTorrent returns a Torrent for an existing file on disk. If the file does 77 // not exist, attempts to re-fetch the file from the storae backend configured 78 // for namespace in a background goroutine, and returns os.ErrNotExist. 79 func (a *TorrentArchive) GetTorrent(namespace string, d core.Digest) (storage.Torrent, error) { 80 mi, err := a.getMetaInfo(namespace, d) 81 if err != nil { 82 return nil, err 83 } 84 t, err := NewTorrent(a.cas, mi) 85 if err != nil { 86 return nil, fmt.Errorf("initialize torrent: %s", err) 87 } 88 return t, nil 89 } 90 91 // DeleteTorrent moves a torrent to the trash. 92 func (a *TorrentArchive) DeleteTorrent(d core.Digest) error { 93 if err := a.cas.DeleteCacheFile(d.Hex()); err != nil && !os.IsNotExist(err) { 94 return err 95 } 96 return nil 97 }