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  }