// Upload instructs the renter to start tracking a file. The renter will // automatically upload and repair tracked files using a background loop. func (r *Renter) Upload(up modules.FileUploadParams) error { // Check for a nickname conflict. lockID := r.mu.RLock() _, exists := r.files[up.Nickname] r.mu.RUnlock(lockID) if exists { return errors.New("file with that nickname already exists") } // Fill in any missing upload params with sensible defaults. fileInfo, err := os.Stat(up.Filename) if err != nil { return err } // TODO: remove this; default duration should be 0 (indefinite) if up.Duration == 0 { up.Duration = defaultDuration } if up.ErasureCode == nil { up.ErasureCode, _ = NewRSCode(defaultDataPieces, defaultParityPieces) } if up.PieceSize == 0 { if fileInfo.Size() > defaultPieceSize { up.PieceSize = defaultPieceSize } else { up.PieceSize = smallPieceSize } } // Check that we have enough money to finance the upload. err = r.checkWalletBalance(up) if err != nil { return err } // Create file object. f := newFile(up.Nickname, up.ErasureCode, up.PieceSize, uint64(fileInfo.Size())) f.mode = uint32(fileInfo.Mode()) // Add file to renter. lockID = r.mu.Lock() r.files[up.Nickname] = f r.tracking[up.Nickname] = trackedFile{ RepairPath: up.Filename, EndHeight: r.blockHeight + up.Duration, } r.save() r.mu.Unlock(lockID) // Save the .sia file to the renter directory. err = r.saveFile(f) if err != nil { return err } return nil }
// Upload takes an upload parameters, which contain a file to upload, and then // creates a redundant copy of the file on the Sia network. func (r *Renter) Upload(up modules.FileUploadParams) error { // Open the file. handle, err := os.Open(up.Filename) if err != nil { return err } defer handle.Close() // Check for a nickname conflict. lockID := r.mu.RLock() _, exists := r.files[up.Nickname] r.mu.RUnlock(lockID) if exists { return errors.New("file with that nickname already exists") } // Check that the file is less than 5 GiB. fileInfo, err := handle.Stat() if err != nil { return err } // NOTE: The upload max of 5 GiB is temporary and therefore does not have // a constant. This should be removed once micropayments + upload resuming // are in place. 5 GiB is chosen to prevent confusion - on anybody's // machine any file appearing to be under 5 GB will be below the hard // limit. if fileInfo.Size() > 5*1024*1024*1024 { return errors.New("cannot upload a file larger than 5 GB") } // Fill in any missing upload params with sensible defaults. if up.Duration == 0 { up.Duration = defaultDuration } if up.ErasureCode == nil { up.ErasureCode, _ = NewRSCode(defaultDataPieces, defaultParityPieces) } if up.PieceSize == 0 { if fileInfo.Size() > defaultPieceSize { up.PieceSize = defaultPieceSize } else { up.PieceSize = smallPieceSize } } // Check that we have enough money to finance the upload. err = r.checkWalletBalance(up) if err != nil { return err } // Create file object. f := newFile(up.Nickname, up.ErasureCode, up.PieceSize, uint64(fileInfo.Size())) f.mode = uint32(fileInfo.Mode()) // Select and connect to hosts. totalsize := up.PieceSize * uint64(up.ErasureCode.NumPieces()) * f.numChunks() var hosts []uploader randHosts := r.hostDB.RandomHosts(up.ErasureCode.NumPieces()) for i := range randHosts { hostUploader, err := r.newHostUploader(randHosts[i], totalsize, up.Duration, f.masterKey) if err != nil { r.log.Printf("Upload: could not form contract with %v: %v", randHosts[i].IPAddress, err) continue } defer hostUploader.Close() hosts = append(hosts, hostUploader) } if len(hosts) < up.ErasureCode.MinPieces() { return errors.New("not enough hosts to support upload") } // Add file to renter. lockID = r.mu.Lock() r.files[up.Nickname] = f r.save() r.mu.Unlock(lockID) // Upload in parallel. err = f.upload(handle, hosts) if err != nil { // Upload failed; remove the file object. lockID = r.mu.Lock() delete(r.files, up.Nickname) r.save() r.mu.Unlock(lockID) return errors.New("failed to upload any file pieces") } // Add file to repair set. lockID = r.mu.Lock() r.repairSet[up.Nickname] = up.Filename r.save() r.mu.Unlock(lockID) // Save the .sia file to the renter directory. err = r.saveFile(f) if err != nil { return err } return nil }
// Upload instructs the renter to start tracking a file. The renter will // automatically upload and repair tracked files using a background loop. func (r *Renter) Upload(up modules.FileUploadParams) error { // Enforce nickname rules. if strings.HasPrefix(up.SiaPath, "/") { return errors.New("nicknames cannot begin with /") } // Check for a nickname conflict. lockID := r.mu.RLock() _, exists := r.files[up.SiaPath] r.mu.RUnlock(lockID) if exists { return ErrPathOverload } // Fill in any missing upload params with sensible defaults. fileInfo, err := os.Stat(up.Source) if err != nil { return err } if up.Duration == 0 { up.Duration = defaultDuration } endHeight := r.cs.Height() + up.Duration if up.ErasureCode == nil { up.ErasureCode, _ = NewRSCode(defaultDataPieces, defaultParityPieces) } if up.PieceSize == 0 { if fileInfo.Size() > defaultPieceSize { up.PieceSize = defaultPieceSize } else { up.PieceSize = smallPieceSize } } // Check that we have enough money to finance the upload. err = r.checkWalletBalance(up) if err != nil { return err } // Create file object. f := newFile(up.SiaPath, up.ErasureCode, up.PieceSize, uint64(fileInfo.Size())) f.mode = uint32(fileInfo.Mode()) // Add file to renter. lockID = r.mu.Lock() r.files[up.SiaPath] = f r.tracking[up.SiaPath] = trackedFile{ RepairPath: up.Source, EndHeight: endHeight, Renew: up.Renew, } r.save() r.mu.Unlock(lockID) // Save the .sia file to the renter directory. err = r.saveFile(f) if err != nil { return err } return nil }
// Upload instructs the renter to start tracking a file. The renter will // automatically upload and repair tracked files using a background loop. func (r *Renter) Upload(up modules.FileUploadParams) error { // Check for a nickname conflict. lockID := r.mu.RLock() _, exists := r.files[up.Nickname] r.mu.RUnlock(lockID) if exists { return errors.New("file with that nickname already exists") } // Check that the file is less than 5 GiB. fileInfo, err := os.Stat(up.Filename) if err != nil { return err } // NOTE: The upload max of 20 GiB is temporary and therefore does not have // a constant. This should be removed once micropayments + upload resuming // are in place. 20 GiB is chosen to prevent confusion - on anybody's // machine any file appearing to be under 20 GB will be below the hard // limit. if fileInfo.Size() > 20*1024*1024*1024 { return errors.New("cannot upload a file larger than 20 GB") } // Fill in any missing upload params with sensible defaults. if up.Duration == 0 { up.Duration = defaultDuration } if up.ErasureCode == nil { up.ErasureCode, _ = NewRSCode(defaultDataPieces, defaultParityPieces) } if up.PieceSize == 0 { if fileInfo.Size() > defaultPieceSize { up.PieceSize = defaultPieceSize } else { up.PieceSize = smallPieceSize } } // Check that we have enough money to finance the upload. err = r.checkWalletBalance(up) if err != nil { return err } // Create file object. f := newFile(up.Nickname, up.ErasureCode, up.PieceSize, uint64(fileInfo.Size())) f.mode = uint32(fileInfo.Mode()) // Add file to renter. lockID = r.mu.Lock() r.files[up.Nickname] = f r.repairSet[up.Nickname] = up.Filename r.save() r.mu.Unlock(lockID) // Save the .sia file to the renter directory. err = r.saveFile(f) if err != nil { return err } return nil }