OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / go / expvar / expvar.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package expvar provides a standardized interface to public variables, such
6 // as operation counters in servers. It exposes these variables via HTTP at
7 // /debug/vars in JSON format.
8 //
9 // Operations to set or modify these public variables are atomic.
10 //
11 // In addition to adding the HTTP handler, this package registers the
12 // following variables:
13 //
14 //      cmdline   os.Args
15 //      memstats  runtime.Memstats
16 //
17 // The package is sometimes only imported for the side effect of
18 // registering its HTTP handler and the above variables.  To use it
19 // this way, simply link this package into your program:
20 //      import _ "expvar"
21 //
22 package expvar
23
24 import (
25         "bytes"
26         "fmt"
27         "http"
28         "json"
29         "log"
30         "os"
31         "runtime"
32         "strconv"
33         "sync"
34 )
35
36 // Var is an abstract type for all exported variables.
37 type Var interface {
38         String() string
39 }
40
41 // Int is a 64-bit integer variable that satisfies the Var interface.
42 type Int struct {
43         i  int64
44         mu sync.Mutex
45 }
46
47 func (v *Int) String() string { return strconv.Itoa64(v.i) }
48
49 func (v *Int) Add(delta int64) {
50         v.mu.Lock()
51         defer v.mu.Unlock()
52         v.i += delta
53 }
54
55 func (v *Int) Set(value int64) {
56         v.mu.Lock()
57         defer v.mu.Unlock()
58         v.i = value
59 }
60
61 // Float is a 64-bit float variable that satisfies the Var interface.
62 type Float struct {
63         f  float64
64         mu sync.Mutex
65 }
66
67 func (v *Float) String() string { return strconv.Ftoa64(v.f, 'g', -1) }
68
69 // Add adds delta to v.
70 func (v *Float) Add(delta float64) {
71         v.mu.Lock()
72         defer v.mu.Unlock()
73         v.f += delta
74 }
75
76 // Set sets v to value.
77 func (v *Float) Set(value float64) {
78         v.mu.Lock()
79         defer v.mu.Unlock()
80         v.f = value
81 }
82
83 // Map is a string-to-Var map variable that satisfies the Var interface.
84 type Map struct {
85         m  map[string]Var
86         mu sync.Mutex
87 }
88
89 // KeyValue represents a single entry in a Map.
90 type KeyValue struct {
91         Key   string
92         Value Var
93 }
94
95 func (v *Map) String() string {
96         v.mu.Lock()
97         defer v.mu.Unlock()
98         b := new(bytes.Buffer)
99         fmt.Fprintf(b, "{")
100         first := true
101         for key, val := range v.m {
102                 if !first {
103                         fmt.Fprintf(b, ", ")
104                 }
105                 fmt.Fprintf(b, "\"%s\": %v", key, val.String())
106                 first = false
107         }
108         fmt.Fprintf(b, "}")
109         return b.String()
110 }
111
112 func (v *Map) Init() *Map {
113         v.m = make(map[string]Var)
114         return v
115 }
116
117 func (v *Map) Get(key string) Var {
118         v.mu.Lock()
119         defer v.mu.Unlock()
120         return v.m[key]
121 }
122
123 func (v *Map) Set(key string, av Var) {
124         v.mu.Lock()
125         defer v.mu.Unlock()
126         v.m[key] = av
127 }
128
129 func (v *Map) Add(key string, delta int64) {
130         v.mu.Lock()
131         defer v.mu.Unlock()
132         av, ok := v.m[key]
133         if !ok {
134                 av = new(Int)
135                 v.m[key] = av
136         }
137
138         // Add to Int; ignore otherwise.
139         if iv, ok := av.(*Int); ok {
140                 iv.Add(delta)
141         }
142 }
143
144 // AddFloat adds delta to the *Float value stored under the given map key.
145 func (v *Map) AddFloat(key string, delta float64) {
146         v.mu.Lock()
147         defer v.mu.Unlock()
148         av, ok := v.m[key]
149         if !ok {
150                 av = new(Float)
151                 v.m[key] = av
152         }
153
154         // Add to Float; ignore otherwise.
155         if iv, ok := av.(*Float); ok {
156                 iv.Add(delta)
157         }
158 }
159
160 // TODO(rsc): Make sure map access in separate thread is safe.
161 func (v *Map) iterate(c chan<- KeyValue) {
162         for k, v := range v.m {
163                 c <- KeyValue{k, v}
164         }
165         close(c)
166 }
167
168 func (v *Map) Iter() <-chan KeyValue {
169         c := make(chan KeyValue)
170         go v.iterate(c)
171         return c
172 }
173
174 // String is a string variable, and satisfies the Var interface.
175 type String struct {
176         s string
177 }
178
179 func (v *String) String() string { return strconv.Quote(v.s) }
180
181 func (v *String) Set(value string) { v.s = value }
182
183 // Func implements Var by calling the function
184 // and formatting the returned value using JSON.
185 type Func func() interface{}
186
187 func (f Func) String() string {
188         v, _ := json.Marshal(f())
189         return string(v)
190 }
191
192 // All published variables.
193 var vars map[string]Var = make(map[string]Var)
194 var mutex sync.Mutex
195
196 // Publish declares an named exported variable. This should be called from a
197 // package's init function when it creates its Vars. If the name is already
198 // registered then this will log.Panic.
199 func Publish(name string, v Var) {
200         mutex.Lock()
201         defer mutex.Unlock()
202         if _, existing := vars[name]; existing {
203                 log.Panicln("Reuse of exported var name:", name)
204         }
205         vars[name] = v
206 }
207
208 // Get retrieves a named exported variable.
209 func Get(name string) Var {
210         return vars[name]
211 }
212
213 // RemoveAll removes all exported variables.
214 // This is for tests; don't call this on a real server.
215 func RemoveAll() {
216         mutex.Lock()
217         defer mutex.Unlock()
218         vars = make(map[string]Var)
219 }
220
221 // Convenience functions for creating new exported variables.
222
223 func NewInt(name string) *Int {
224         v := new(Int)
225         Publish(name, v)
226         return v
227 }
228
229 func NewFloat(name string) *Float {
230         v := new(Float)
231         Publish(name, v)
232         return v
233 }
234
235 func NewMap(name string) *Map {
236         v := new(Map).Init()
237         Publish(name, v)
238         return v
239 }
240
241 func NewString(name string) *String {
242         v := new(String)
243         Publish(name, v)
244         return v
245 }
246
247 // TODO(rsc): Make sure map access in separate thread is safe.
248 func iterate(c chan<- KeyValue) {
249         for k, v := range vars {
250                 c <- KeyValue{k, v}
251         }
252         close(c)
253 }
254
255 func Iter() <-chan KeyValue {
256         c := make(chan KeyValue)
257         go iterate(c)
258         return c
259 }
260
261 func expvarHandler(w http.ResponseWriter, r *http.Request) {
262         w.Header().Set("Content-Type", "application/json; charset=utf-8")
263         fmt.Fprintf(w, "{\n")
264         first := true
265         for name, value := range vars {
266                 if !first {
267                         fmt.Fprintf(w, ",\n")
268                 }
269                 first = false
270                 fmt.Fprintf(w, "%q: %s", name, value)
271         }
272         fmt.Fprintf(w, "\n}\n")
273 }
274
275 func cmdline() interface{} {
276         return os.Args
277 }
278
279 func memstats() interface{} {
280         return runtime.MemStats
281 }
282
283 func init() {
284         http.Handle("/debug/vars", http.HandlerFunc(expvarHandler))
285         Publish("cmdline", Func(cmdline))
286         Publish("memstats", Func(memstats))
287 }