/
controller.go
77 lines (65 loc) · 1.32 KB
/
controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main
import (
"fmt"
"log"
"strings"
"sync/atomic"
"time"
"github.com/dustin/gomemcached"
)
const numCommands = 3
const readySize = 1024
var stats [256]int64
type Command struct {
Cmd gomemcached.CommandCode
Key string
VBucket uint16
}
type Result struct {
Error error
Res *gomemcached.MCResponse
}
func NewController(numKeys int) chan<- Result {
responses := make(chan Result)
go handleResults(responses)
return responses
}
func report(tdiff int64) {
var total float32 = 0
trailer := []string{}
for i, v := range stats {
total += float32(v)
if v > 0 {
trailer = append(trailer,
fmt.Sprintf("%s: %v",
gomemcached.CommandCode(i), v))
atomic.AddInt64(&stats[i], 0-v)
}
}
log.Printf("%.2f ops/s (%s)",
total/float32(tdiff),
strings.Join(trailer, ", "))
}
func handleResults(ch <-chan Result) {
reportSignaler := time.NewTicker(time.Second * 5)
prev := time.Now()
for {
select {
// Do we need to report?
case now := <-reportSignaler.C:
report((now.Unix() - prev.Unix()))
prev = now
// Do we have a result?
case result := <-ch:
if result.Error != nil {
log.Printf("Got an error: %v", result.Error)
} else {
if result.Res.Status != 0 {
log.Printf("Response from %s: %s",
result.Res.Opcode,
result.Res.Status)
}
}
}
}
}