gifs/api
2014-10-17
Parent:b5d88d57d587
gifs/api/upload.go
Make UsageTracker an interface, ditch the channel interface. Stop using channels to track usage. Just call functions. Make UsageTracker an interface, so there can be multiple implementations, and create the in-memory implementation.
| paddy@0 | 1 package api |
| paddy@0 | 2 |
| paddy@0 | 3 import ( |
| paddy@0 | 4 "crypto/sha1" |
| paddy@0 | 5 "encoding/hex" |
| paddy@0 | 6 "io" |
| paddy@0 | 7 |
| paddy@5 | 8 "code.secondbit.org/uuid.hg" |
| paddy@0 | 9 ) |
| paddy@0 | 10 |
| paddy@5 | 11 func upload(store Storage, bucket, name string, data *io.PipeReader, done chan struct{}) { |
| paddy@5 | 12 err := store.Upload(bucket, name, data) |
| paddy@5 | 13 if err != nil { |
| paddy@5 | 14 data.CloseWithError(err) |
| paddy@5 | 15 return |
| paddy@5 | 16 } |
| paddy@5 | 17 close(done) |
| paddy@5 | 18 } |
| paddy@5 | 19 |
| paddy@0 | 20 func Upload(collectionID uuid.ID, r io.Reader, c Context) (Item, int64, error) { |
| paddy@5 | 21 h := sha1.New() |
| paddy@5 | 22 var w io.Writer |
| paddy@0 | 23 uploadReader, uploadWriter := io.Pipe() |
| paddy@5 | 24 uploadChan := make(chan struct{}) |
| paddy@5 | 25 tmp := uuid.NewID().String() |
| paddy@0 | 26 |
| paddy@0 | 27 if c.Storage != nil { |
| paddy@5 | 28 w = io.MultiWriter(h, uploadWriter) |
| paddy@5 | 29 go upload(c.Storage, c.TmpBucket, tmp, uploadReader, uploadChan) |
| paddy@5 | 30 } else { |
| paddy@5 | 31 w = h |
| paddy@5 | 32 close(uploadChan) |
| paddy@0 | 33 } |
| paddy@0 | 34 |
| paddy@5 | 35 size, err := io.Copy(w, r) |
| paddy@5 | 36 if err != nil { |
| paddy@5 | 37 if c.Storage != nil { |
| paddy@0 | 38 uploadWriter.Close() |
| paddy@0 | 39 } |
| paddy@5 | 40 return Item{}, 0, err |
| paddy@0 | 41 } |
| paddy@5 | 42 |
| paddy@5 | 43 finalLocation := hex.EncodeToString(h.Sum(nil)) |
| paddy@5 | 44 uploadWriter.Close() |
| paddy@5 | 45 <-uploadChan |
| paddy@5 | 46 |
| paddy@0 | 47 if c.Storage != nil { |
| paddy@5 | 48 err = c.Storage.Move(c.TmpBucket, tmp, c.Bucket, finalLocation) |
| paddy@0 | 49 if err != nil { |
| paddy@0 | 50 return Item{}, 0, err |
| paddy@0 | 51 } |
| paddy@0 | 52 } |
| paddy@0 | 53 return Item{ |
| paddy@0 | 54 Blob: finalLocation, |
| paddy@0 | 55 Bucket: c.Bucket, |
| paddy@0 | 56 CollectionID: collectionID, |
| paddy@5 | 57 }, size, nil |
| paddy@0 | 58 } |