storj.io/uplink@v1.13.0/private/storage/streams/upload.go (about)

     1  // Copyright (C) 2023 Storj Labs, Inc.
     2  // See LICENSE for copying information.
     3  
     4  package streams
     5  
     6  import (
     7  	"sync"
     8  
     9  	"github.com/zeebo/errs"
    10  
    11  	"storj.io/uplink/private/storage/streams/splitter"
    12  	"storj.io/uplink/private/storage/streams/streamupload"
    13  )
    14  
    15  type uploadResult struct {
    16  	info streamupload.Info
    17  	err  error
    18  }
    19  
    20  // Upload represents an object or part upload and is returned by PutWriter or
    21  // PutWriterPart. Data to be uploaded is written using the Write call. Either
    22  // Commit or Abort must be called to either complete the upload or otherwise
    23  // free up resources related to the upload.
    24  type Upload struct {
    25  	mu     sync.Mutex
    26  	split  *splitter.Splitter
    27  	done   chan uploadResult
    28  	info   streamupload.Info
    29  	cancel func()
    30  }
    31  
    32  // Write uploads the object or part data.
    33  func (u *Upload) Write(p []byte) (int, error) {
    34  	u.mu.Lock()
    35  	defer u.mu.Unlock()
    36  
    37  	if u.done == nil {
    38  		return 0, errs.New("upload already done")
    39  	}
    40  
    41  	return u.split.Write(p)
    42  }
    43  
    44  // Abort aborts the upload. If called more than once, or after Commit, it will
    45  // return an error.
    46  func (u *Upload) Abort() error {
    47  	u.split.Finish(errs.New("aborted"))
    48  	u.cancel()
    49  
    50  	u.mu.Lock()
    51  	defer u.mu.Unlock()
    52  
    53  	if u.done == nil {
    54  		return errs.New("upload already done")
    55  	}
    56  	<-u.done
    57  	u.done = nil
    58  
    59  	return nil
    60  }
    61  
    62  // Commit commits the upload and must be called for the upload to complete
    63  // successfully. It should only be called after all of the data has been
    64  // written.
    65  func (u *Upload) Commit() error {
    66  	u.split.Finish(nil)
    67  
    68  	u.mu.Lock()
    69  	defer u.mu.Unlock()
    70  
    71  	if u.done == nil {
    72  		return errs.New("upload already done")
    73  	}
    74  	result := <-u.done
    75  	u.info = result.info
    76  	u.done = nil
    77  
    78  	u.cancel()
    79  	return result.err
    80  }
    81  
    82  // Meta returns the upload metadata. It should only be called after a
    83  // successful Commit and will return nil otherwise.
    84  func (u *Upload) Meta() *Meta {
    85  	u.mu.Lock()
    86  	defer u.mu.Unlock()
    87  
    88  	if u.done != nil {
    89  		return nil
    90  	}
    91  
    92  	return &Meta{
    93  		Modified: u.info.CreationDate,
    94  		Size:     u.info.PlainSize,
    95  		Version:  u.info.Version,
    96  	}
    97  }