github.com/orofarne/hammy@v0.0.0-20130409105742-374fadfd6ecb/src/hammy/send_buffer.go (about) 1 package hammy 2 3 import ( 4 "log" 5 "time" 6 "container/list" 7 "encoding/json" 8 ) 9 10 // Buffer for reprocessed data 11 type SendBufferImpl struct { 12 dataChan chan *IncomingData 13 data *list.List 14 // Timeout between sends 15 sleepTime time.Duration 16 rHandler RequestHandler 17 18 //Metics 19 ms *MetricSet 20 mPushes *CounterMetric 21 mSendedValues *CounterMetric 22 mSend *TimerMetric 23 mErrors *CounterMetric 24 } 25 26 // Creates and initialize new SendBuffer 27 func NewSendBufferImpl(rh RequestHandler, cfg Config, metricsNamespace string) (sb *SendBufferImpl) { 28 sb = new(SendBufferImpl) 29 sb.dataChan = make(chan *IncomingData) 30 sb.data = list.New() 31 sb.sleepTime = time.Duration(1000 * cfg.SendBuffer.SleepTime) * time.Millisecond 32 sb.rHandler = rh 33 34 sb.ms = NewMetricSet(metricsNamespace, 30*time.Second) 35 sb.mPushes = sb.ms.NewCounter("pushes") 36 sb.mSendedValues = sb.ms.NewCounter("sended_values") 37 sb.mSend = sb.ms.NewTimer("send") 38 sb.mErrors = sb.ms.NewCounter("errors") 39 40 return 41 } 42 43 // Locks and begins data processing 44 func (sb *SendBufferImpl) Listen() { 45 timer := time.Tick(sb.sleepTime) 46 47 for { 48 select { 49 case newData := <- sb.dataChan: 50 sb.data.PushBack(newData) 51 case <- timer: 52 go sb.send(sb.data) 53 sb.data = list.New() 54 } 55 } 56 } 57 58 // Enqueue data for reprocessing 59 func (sb *SendBufferImpl) Push(data *IncomingData) { 60 sb.dataChan <- data 61 sb.mPushes.Add(1) 62 } 63 64 // Process detached data buffer 65 func (sb *SendBufferImpl) send(data *list.List) { 66 if data.Len() == 0 { 67 return 68 } 69 70 // Statistics 71 τ := sb.mSend.NewObservation() 72 defer func() { τ.End() } () 73 var sended_values uint64 74 75 // 1) Merge list 76 mData := make(IncomingData) 77 // iterates over data list 78 for e := data.Front(); e != nil; e = e.Next() { 79 // e.Value is *IncomingData (panic otherwise) 80 eData := e.Value.(*IncomingData) 81 for hostK, hostV := range *eData { 82 mV, hostFound := mData[hostK] 83 if hostFound { 84 for k, v := range hostV { 85 iArr, kFound := mV[k] 86 if kFound { 87 newIArr := make([]IncomingValueData, len(v) + len(iArr)) 88 for i, vE := range iArr { 89 newIArr[i] = vE 90 sended_values++ // Statistics 91 } 92 for j, vE := range v { 93 newIArr[len(iArr) + j] = vE 94 sended_values++ // Statistics 95 } 96 mV[k] = newIArr 97 } else { 98 mV[k] = v 99 } 100 } 101 } else { 102 mData[hostK] = hostV 103 } 104 } 105 } 106 107 sb.mSendedValues.Add(sended_values) // Statistics 108 109 // 2) Process merged data 110 errs := sb.rHandler.Handle(mData) 111 112 if len(errs) > 0 { 113 sb.mErrors.Add(uint64(len(errs))) // Statistics 114 115 // FIXME 116 errs_str := make(map[string]string) 117 for k, v := range errs { 118 errs_str[k] = v.Error() 119 } 120 b, err := json.Marshal(errs_str) 121 if err == nil { 122 log.Printf("!! Error in SendBuffer: %s", b) 123 } else { 124 log.Printf("!! Error in SendBuffer: <unable to dump errs: %#v>", err) 125 } 126 } 127 }