github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/renter/upload.go (about)

     1  package renter
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/NebulousLabs/Sia/build"
     9  	"github.com/NebulousLabs/Sia/crypto"
    10  	"github.com/NebulousLabs/Sia/modules"
    11  )
    12  
    13  var (
    14  	errInsufficientContracts = errors.New("not enough contracts to upload file")
    15  
    16  	// Erasure-coded piece size
    17  	pieceSize = modules.SectorSize - crypto.TwofishOverhead
    18  
    19  	// defaultDataPieces is the number of data pieces per erasure-coded chunk
    20  	defaultDataPieces = func() int {
    21  		if build.Release == "testing" {
    22  			return 1
    23  		}
    24  		return 4
    25  	}()
    26  
    27  	// defaultParityPieces is the number of parity pieces per erasure-coded
    28  	// chunk
    29  	defaultParityPieces = func() int {
    30  		if build.Release == "testing" {
    31  			return 8
    32  		}
    33  		return 20
    34  	}()
    35  )
    36  
    37  // Upload instructs the renter to start tracking a file. The renter will
    38  // automatically upload and repair tracked files using a background loop.
    39  func (r *Renter) Upload(up modules.FileUploadParams) error {
    40  	// Enforce nickname rules.
    41  	if strings.HasPrefix(up.SiaPath, "/") {
    42  		return errors.New("nicknames cannot begin with /")
    43  	}
    44  
    45  	if !r.wallet.Unlocked() {
    46  		return errors.New("wallet must be unlocked before uploading")
    47  	}
    48  
    49  	// Check for a nickname conflict.
    50  	lockID := r.mu.RLock()
    51  	_, exists := r.files[up.SiaPath]
    52  	r.mu.RUnlock(lockID)
    53  	if exists {
    54  		return ErrPathOverload
    55  	}
    56  
    57  	// Fill in any missing upload params with sensible defaults.
    58  	fileInfo, err := os.Stat(up.Source)
    59  	if err != nil {
    60  		return err
    61  	}
    62  	if up.ErasureCode == nil {
    63  		up.ErasureCode, _ = NewRSCode(defaultDataPieces, defaultParityPieces)
    64  	}
    65  
    66  	// Check that we have contracts to upload to.
    67  	if len(r.hostContractor.Contracts()) < up.ErasureCode.NumPieces() && build.Release != "testing" {
    68  		return errInsufficientContracts
    69  	}
    70  
    71  	// Create file object.
    72  	f := newFile(up.SiaPath, up.ErasureCode, pieceSize, uint64(fileInfo.Size()))
    73  	f.mode = uint32(fileInfo.Mode())
    74  
    75  	// Add file to renter.
    76  	lockID = r.mu.Lock()
    77  	r.files[up.SiaPath] = f
    78  	r.tracking[up.SiaPath] = trackedFile{
    79  		RepairPath: up.Source,
    80  	}
    81  	r.saveSync()
    82  	r.mu.Unlock(lockID)
    83  
    84  	// Save the .sia file to the renter directory.
    85  	err = r.saveFile(f)
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	return nil
    91  }