gifs/api
gifs/api/usage.go
Simplify upload. Simplify the upload code by not running the hashing async, which requires fewer copy operations and less channel synchronization. Also, take advantage of the fact that PipeWriters and PipeReaders will return an error to the PipeReaders/PipeWriters (respectively) when read/write is called (respectively) to avoid passing back errors through channels.
| paddy@0 | 1 package api |
| paddy@0 | 2 |
| paddy@0 | 3 import ( |
| paddy@0 | 4 "sync" |
| paddy@0 | 5 ) |
| paddy@0 | 6 |
| paddy@0 | 7 func NewUsageTracker() *UsageTracker { |
| paddy@0 | 8 return &UsageTracker{ |
| paddy@0 | 9 usages: make(map[string]*Usage), |
| paddy@0 | 10 } |
| paddy@0 | 11 } |
| paddy@0 | 12 |
| paddy@0 | 13 type UsageTracker struct { |
| paddy@0 | 14 usages map[string]*Usage |
| paddy@0 | 15 sync.Mutex |
| paddy@0 | 16 } |
| paddy@0 | 17 |
| paddy@0 | 18 func (u *UsageTracker) TrackUploads(id string) (bytes, requests chan int64) { |
| paddy@0 | 19 u.Lock() |
| paddy@0 | 20 defer u.Unlock() |
| paddy@0 | 21 if _, ok := u.usages[id]; !ok { |
| paddy@0 | 22 u.usages[id] = &Usage{ |
| paddy@0 | 23 UploadBytesChan: make(chan int64), |
| paddy@0 | 24 DownloadBytesChan: make(chan int64), |
| paddy@0 | 25 UploadRequestsChan: make(chan int64), |
| paddy@0 | 26 DownloadRequestsChan: make(chan int64), |
| paddy@0 | 27 } |
| paddy@0 | 28 go u.usages[id].collect() |
| paddy@0 | 29 } |
| paddy@0 | 30 return u.usages[id].UploadBytesChan, u.usages[id].UploadRequestsChan |
| paddy@0 | 31 } |
| paddy@0 | 32 |
| paddy@0 | 33 func (u *UsageTracker) TrackDownloads(id string) (bytes, requests chan int64) { |
| paddy@0 | 34 u.Lock() |
| paddy@0 | 35 defer u.Unlock() |
| paddy@0 | 36 if _, ok := u.usages[id]; !ok { |
| paddy@0 | 37 u.usages[id] = &Usage{ |
| paddy@0 | 38 UploadBytesChan: make(chan int64), |
| paddy@0 | 39 DownloadBytesChan: make(chan int64), |
| paddy@0 | 40 UploadRequestsChan: make(chan int64), |
| paddy@0 | 41 DownloadRequestsChan: make(chan int64), |
| paddy@0 | 42 } |
| paddy@0 | 43 go u.usages[id].collect() |
| paddy@0 | 44 } |
| paddy@0 | 45 return u.usages[id].DownloadBytesChan, u.usages[id].DownloadRequestsChan |
| paddy@0 | 46 } |
| paddy@0 | 47 |
| paddy@0 | 48 type Usage struct { |
| paddy@0 | 49 UploadedBytes int64 |
| paddy@0 | 50 UploadBytesChan chan int64 |
| paddy@0 | 51 DownloadedBytes int64 |
| paddy@0 | 52 DownloadBytesChan chan int64 |
| paddy@0 | 53 UploadRequests int64 |
| paddy@0 | 54 UploadRequestsChan chan int64 |
| paddy@0 | 55 DownloadRequests int64 |
| paddy@0 | 56 DownloadRequestsChan chan int64 |
| paddy@0 | 57 } |
| paddy@0 | 58 |
| paddy@0 | 59 func (u *Usage) collect() { |
| paddy@0 | 60 for { |
| paddy@0 | 61 select { |
| paddy@0 | 62 case b, ok := <-u.UploadBytesChan: |
| paddy@0 | 63 if !ok { |
| paddy@0 | 64 u.UploadBytesChan = nil |
| paddy@0 | 65 } |
| paddy@0 | 66 u.UploadedBytes += b |
| paddy@0 | 67 case r, ok := <-u.UploadRequestsChan: |
| paddy@0 | 68 if !ok { |
| paddy@0 | 69 u.UploadRequestsChan = nil |
| paddy@0 | 70 } |
| paddy@0 | 71 u.UploadRequests += r |
| paddy@0 | 72 case b, ok := <-u.DownloadBytesChan: |
| paddy@0 | 73 if !ok { |
| paddy@0 | 74 u.DownloadBytesChan = nil |
| paddy@0 | 75 } |
| paddy@0 | 76 u.DownloadedBytes += b |
| paddy@0 | 77 case r, ok := <-u.DownloadRequestsChan: |
| paddy@0 | 78 if !ok { |
| paddy@0 | 79 u.DownloadRequestsChan = nil |
| paddy@0 | 80 } |
| paddy@0 | 81 u.DownloadRequests += r |
| paddy@0 | 82 } |
| paddy@0 | 83 if u.UploadBytesChan == nil && u.UploadRequestsChan == nil && u.DownloadBytesChan == nil && u.DownloadRequestsChan == nil { |
| paddy@0 | 84 break |
| paddy@0 | 85 } |
| paddy@0 | 86 } |
| paddy@0 | 87 } |