gifs/api

Paddy 2014-10-17 Parent:08ec88016e2f Child:eb450538f079

4:1bbbe113f599 Go to Latest

gifs/api/usage.go

Upload is no longer async, memstorage is parallel-safe. Upload no longer needs to be run async (it can be run inside a goroutine), so it now returns stuff instead of taking a channel as an argument. This will make it easier to implement, as all the async stuff is an abstraction above, and therefore doesn't need to be worried about for each reimplementation. The memstorage type is no longer exported and can now be safely used by multiple goroutines, thanks to the sync package.

History
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 }