ducky/devices

Paddy 2015-12-14 Parent:b6494e1a499e

15:c24a6c5fcd8c Go to Latest

ducky/devices/vendor/golang.org/x/net/context/context.go

Begin implementation on apiv1. Begin implementing the apiv1 package, which will define the first iteration of our API endpoints and logic. Each API package should be self-contained and able to run without depending on each other. Think of them as interfaces into manipulating the business logic defined in the devices package. The point is to have total control over backwards compatibility, as long as our business logic doesn't change. If that happens, we're in a bad place, but not as bad as it could be. This required us to pull in all our API tools; the api package, its dependencies, the scopeTypes package (so we can define scopes for our API), the trout router, etc. We also updated uuid to the latest, which now includes a license. Hooray? The new apiv1 package consists of a few things: * The devices.go file defines the types the API will use to communicate, along with some helpers to convert from API types to devices types. There's also a stub for validating the device creation requests, which I haven't implemented yet because I'm a pretty bad person. * endpoints.go just contains a helper function that builds our routes and assigns handlers to them, giving us an http.Handler in the returns that we can listen with. * handlers.go defines our HTTP handlers, which will read requests and write responses, after doing the appropriate validation and executing the appropriating business logic. Right now, we only have a handler for creating devices, and it doesn't actually do any validation. Also, we have some user-correctable errors being returned as 500s right now, which is Bad. Fortunately, they're all marked with BUG, so I can at least come back to them. * response.go defines the Response type that will be used for returning information after a request is executed. It may eventually get some helpers, but for now it's pretty basic. * scopes.go defines the Scopes that we're going to be using in the package to control access. It should probably (eventually) include a helper to register the Scopes, or we should have a collector service that pulls in all the packages, finds all their Scopes, and registers them. I haven't decided how I want to manage Scope registration just yet. We exported the getStorer function (now GetStorer) so other packages can use it. I'm not sure how I feel about this just yet. We also had to create a WithStorer helper method that embeds the Storer into a context.Context, so we can bootstrap in devicesd. We erroneously had Created in the DeviceChange struct, but there's no reason the Created property of a Device should ever change, so it was removed from the logic, from the struct, and from the tests. Our CreateMany helper was erroneously creating the un-modified Devices that were passed in, instead of the Devices that had sensible defaults filled. We created a _very minimal_ (e.g., needs some work before it's ready for production) devicesd package that will spin up a simple server, just so we could take a peek at our apiv1 endpoints as they'd actually be used. (It worked. Yay?) We should continue to expand on this with configuration, more information being logged, etc.

History
1 // Copyright 2014 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.
5 // Package context defines the Context type, which carries deadlines,
6 // cancelation signals, and other request-scoped values across API boundaries
7 // and between processes.
8 //
9 // Incoming requests to a server should create a Context, and outgoing calls to
10 // servers should accept a Context. The chain of function calls between must
11 // propagate the Context, optionally replacing it with a modified copy created
12 // using WithDeadline, WithTimeout, WithCancel, or WithValue.
13 //
14 // Programs that use Contexts should follow these rules to keep interfaces
15 // consistent across packages and enable static analysis tools to check context
16 // propagation:
17 //
18 // Do not store Contexts inside a struct type; instead, pass a Context
19 // explicitly to each function that needs it. The Context should be the first
20 // parameter, typically named ctx:
21 //
22 // func DoSomething(ctx context.Context, arg Arg) error {
23 // // ... use ctx ...
24 // }
25 //
26 // Do not pass a nil Context, even if a function permits it. Pass context.TODO
27 // if you are unsure about which Context to use.
28 //
29 // Use context Values only for request-scoped data that transits processes and
30 // APIs, not for passing optional parameters to functions.
31 //
32 // The same Context may be passed to functions running in different goroutines;
33 // Contexts are safe for simultaneous use by multiple goroutines.
34 //
35 // See http://blog.golang.org/context for example code for a server that uses
36 // Contexts.
37 package context
39 import (
40 "errors"
41 "fmt"
42 "sync"
43 "time"
44 )
46 // A Context carries a deadline, a cancelation signal, and other values across
47 // API boundaries.
48 //
49 // Context's methods may be called by multiple goroutines simultaneously.
50 type Context interface {
51 // Deadline returns the time when work done on behalf of this context
52 // should be canceled. Deadline returns ok==false when no deadline is
53 // set. Successive calls to Deadline return the same results.
54 Deadline() (deadline time.Time, ok bool)
56 // Done returns a channel that's closed when work done on behalf of this
57 // context should be canceled. Done may return nil if this context can
58 // never be canceled. Successive calls to Done return the same value.
59 //
60 // WithCancel arranges for Done to be closed when cancel is called;
61 // WithDeadline arranges for Done to be closed when the deadline
62 // expires; WithTimeout arranges for Done to be closed when the timeout
63 // elapses.
64 //
65 // Done is provided for use in select statements:
66 //
67 // // Stream generates values with DoSomething and sends them to out
68 // // until DoSomething returns an error or ctx.Done is closed.
69 // func Stream(ctx context.Context, out <-chan Value) error {
70 // for {
71 // v, err := DoSomething(ctx)
72 // if err != nil {
73 // return err
74 // }
75 // select {
76 // case <-ctx.Done():
77 // return ctx.Err()
78 // case out <- v:
79 // }
80 // }
81 // }
82 //
83 // See http://blog.golang.org/pipelines for more examples of how to use
84 // a Done channel for cancelation.
85 Done() <-chan struct{}
87 // Err returns a non-nil error value after Done is closed. Err returns
88 // Canceled if the context was canceled or DeadlineExceeded if the
89 // context's deadline passed. No other values for Err are defined.
90 // After Done is closed, successive calls to Err return the same value.
91 Err() error
93 // Value returns the value associated with this context for key, or nil
94 // if no value is associated with key. Successive calls to Value with
95 // the same key returns the same result.
96 //
97 // Use context values only for request-scoped data that transits
98 // processes and API boundaries, not for passing optional parameters to
99 // functions.
100 //
101 // A key identifies a specific value in a Context. Functions that wish
102 // to store values in Context typically allocate a key in a global
103 // variable then use that key as the argument to context.WithValue and
104 // Context.Value. A key can be any type that supports equality;
105 // packages should define keys as an unexported type to avoid
106 // collisions.
107 //
108 // Packages that define a Context key should provide type-safe accessors
109 // for the values stores using that key:
110 //
111 // // Package user defines a User type that's stored in Contexts.
112 // package user
113 //
114 // import "golang.org/x/net/context"
115 //
116 // // User is the type of value stored in the Contexts.
117 // type User struct {...}
118 //
119 // // key is an unexported type for keys defined in this package.
120 // // This prevents collisions with keys defined in other packages.
121 // type key int
122 //
123 // // userKey is the key for user.User values in Contexts. It is
124 // // unexported; clients use user.NewContext and user.FromContext
125 // // instead of using this key directly.
126 // var userKey key = 0
127 //
128 // // NewContext returns a new Context that carries value u.
129 // func NewContext(ctx context.Context, u *User) context.Context {
130 // return context.WithValue(ctx, userKey, u)
131 // }
132 //
133 // // FromContext returns the User value stored in ctx, if any.
134 // func FromContext(ctx context.Context) (*User, bool) {
135 // u, ok := ctx.Value(userKey).(*User)
136 // return u, ok
137 // }
138 Value(key interface{}) interface{}
139 }
141 // Canceled is the error returned by Context.Err when the context is canceled.
142 var Canceled = errors.New("context canceled")
144 // DeadlineExceeded is the error returned by Context.Err when the context's
145 // deadline passes.
146 var DeadlineExceeded = errors.New("context deadline exceeded")
148 // An emptyCtx is never canceled, has no values, and has no deadline. It is not
149 // struct{}, since vars of this type must have distinct addresses.
150 type emptyCtx int
152 func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
153 return
154 }
156 func (*emptyCtx) Done() <-chan struct{} {
157 return nil
158 }
160 func (*emptyCtx) Err() error {
161 return nil
162 }
164 func (*emptyCtx) Value(key interface{}) interface{} {
165 return nil
166 }
168 func (e *emptyCtx) String() string {
169 switch e {
170 case background:
171 return "context.Background"
172 case todo:
173 return "context.TODO"
174 }
175 return "unknown empty Context"
176 }
178 var (
179 background = new(emptyCtx)
180 todo = new(emptyCtx)
181 )
183 // Background returns a non-nil, empty Context. It is never canceled, has no
184 // values, and has no deadline. It is typically used by the main function,
185 // initialization, and tests, and as the top-level Context for incoming
186 // requests.
187 func Background() Context {
188 return background
189 }
191 // TODO returns a non-nil, empty Context. Code should use context.TODO when
192 // it's unclear which Context to use or it's is not yet available (because the
193 // surrounding function has not yet been extended to accept a Context
194 // parameter). TODO is recognized by static analysis tools that determine
195 // whether Contexts are propagated correctly in a program.
196 func TODO() Context {
197 return todo
198 }
200 // A CancelFunc tells an operation to abandon its work.
201 // A CancelFunc does not wait for the work to stop.
202 // After the first call, subsequent calls to a CancelFunc do nothing.
203 type CancelFunc func()
205 // WithCancel returns a copy of parent with a new Done channel. The returned
206 // context's Done channel is closed when the returned cancel function is called
207 // or when the parent context's Done channel is closed, whichever happens first.
208 //
209 // Canceling this context releases resources associated with it, so code should
210 // call cancel as soon as the operations running in this Context complete.
211 func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
212 c := newCancelCtx(parent)
213 propagateCancel(parent, &c)
214 return &c, func() { c.cancel(true, Canceled) }
215 }
217 // newCancelCtx returns an initialized cancelCtx.
218 func newCancelCtx(parent Context) cancelCtx {
219 return cancelCtx{
220 Context: parent,
221 done: make(chan struct{}),
222 }
223 }
225 // propagateCancel arranges for child to be canceled when parent is.
226 func propagateCancel(parent Context, child canceler) {
227 if parent.Done() == nil {
228 return // parent is never canceled
229 }
230 if p, ok := parentCancelCtx(parent); ok {
231 p.mu.Lock()
232 if p.err != nil {
233 // parent has already been canceled
234 child.cancel(false, p.err)
235 } else {
236 if p.children == nil {
237 p.children = make(map[canceler]bool)
238 }
239 p.children[child] = true
240 }
241 p.mu.Unlock()
242 } else {
243 go func() {
244 select {
245 case <-parent.Done():
246 child.cancel(false, parent.Err())
247 case <-child.Done():
248 }
249 }()
250 }
251 }
253 // parentCancelCtx follows a chain of parent references until it finds a
254 // *cancelCtx. This function understands how each of the concrete types in this
255 // package represents its parent.
256 func parentCancelCtx(parent Context) (*cancelCtx, bool) {
257 for {
258 switch c := parent.(type) {
259 case *cancelCtx:
260 return c, true
261 case *timerCtx:
262 return &c.cancelCtx, true
263 case *valueCtx:
264 parent = c.Context
265 default:
266 return nil, false
267 }
268 }
269 }
271 // removeChild removes a context from its parent.
272 func removeChild(parent Context, child canceler) {
273 p, ok := parentCancelCtx(parent)
274 if !ok {
275 return
276 }
277 p.mu.Lock()
278 if p.children != nil {
279 delete(p.children, child)
280 }
281 p.mu.Unlock()
282 }
284 // A canceler is a context type that can be canceled directly. The
285 // implementations are *cancelCtx and *timerCtx.
286 type canceler interface {
287 cancel(removeFromParent bool, err error)
288 Done() <-chan struct{}
289 }
291 // A cancelCtx can be canceled. When canceled, it also cancels any children
292 // that implement canceler.
293 type cancelCtx struct {
294 Context
296 done chan struct{} // closed by the first cancel call.
298 mu sync.Mutex
299 children map[canceler]bool // set to nil by the first cancel call
300 err error // set to non-nil by the first cancel call
301 }
303 func (c *cancelCtx) Done() <-chan struct{} {
304 return c.done
305 }
307 func (c *cancelCtx) Err() error {
308 c.mu.Lock()
309 defer c.mu.Unlock()
310 return c.err
311 }
313 func (c *cancelCtx) String() string {
314 return fmt.Sprintf("%v.WithCancel", c.Context)
315 }
317 // cancel closes c.done, cancels each of c's children, and, if
318 // removeFromParent is true, removes c from its parent's children.
319 func (c *cancelCtx) cancel(removeFromParent bool, err error) {
320 if err == nil {
321 panic("context: internal error: missing cancel error")
322 }
323 c.mu.Lock()
324 if c.err != nil {
325 c.mu.Unlock()
326 return // already canceled
327 }
328 c.err = err
329 close(c.done)
330 for child := range c.children {
331 // NOTE: acquiring the child's lock while holding parent's lock.
332 child.cancel(false, err)
333 }
334 c.children = nil
335 c.mu.Unlock()
337 if removeFromParent {
338 removeChild(c.Context, c)
339 }
340 }
342 // WithDeadline returns a copy of the parent context with the deadline adjusted
343 // to be no later than d. If the parent's deadline is already earlier than d,
344 // WithDeadline(parent, d) is semantically equivalent to parent. The returned
345 // context's Done channel is closed when the deadline expires, when the returned
346 // cancel function is called, or when the parent context's Done channel is
347 // closed, whichever happens first.
348 //
349 // Canceling this context releases resources associated with it, so code should
350 // call cancel as soon as the operations running in this Context complete.
351 func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
352 if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
353 // The current deadline is already sooner than the new one.
354 return WithCancel(parent)
355 }
356 c := &timerCtx{
357 cancelCtx: newCancelCtx(parent),
358 deadline: deadline,
359 }
360 propagateCancel(parent, c)
361 d := deadline.Sub(time.Now())
362 if d <= 0 {
363 c.cancel(true, DeadlineExceeded) // deadline has already passed
364 return c, func() { c.cancel(true, Canceled) }
365 }
366 c.mu.Lock()
367 defer c.mu.Unlock()
368 if c.err == nil {
369 c.timer = time.AfterFunc(d, func() {
370 c.cancel(true, DeadlineExceeded)
371 })
372 }
373 return c, func() { c.cancel(true, Canceled) }
374 }
376 // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
377 // implement Done and Err. It implements cancel by stopping its timer then
378 // delegating to cancelCtx.cancel.
379 type timerCtx struct {
380 cancelCtx
381 timer *time.Timer // Under cancelCtx.mu.
383 deadline time.Time
384 }
386 func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
387 return c.deadline, true
388 }
390 func (c *timerCtx) String() string {
391 return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
392 }
394 func (c *timerCtx) cancel(removeFromParent bool, err error) {
395 c.cancelCtx.cancel(false, err)
396 if removeFromParent {
397 // Remove this timerCtx from its parent cancelCtx's children.
398 removeChild(c.cancelCtx.Context, c)
399 }
400 c.mu.Lock()
401 if c.timer != nil {
402 c.timer.Stop()
403 c.timer = nil
404 }
405 c.mu.Unlock()
406 }
408 // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
409 //
410 // Canceling this context releases resources associated with it, so code should
411 // call cancel as soon as the operations running in this Context complete:
412 //
413 // func slowOperationWithTimeout(ctx context.Context) (Result, error) {
414 // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
415 // defer cancel() // releases resources if slowOperation completes before timeout elapses
416 // return slowOperation(ctx)
417 // }
418 func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
419 return WithDeadline(parent, time.Now().Add(timeout))
420 }
422 // WithValue returns a copy of parent in which the value associated with key is
423 // val.
424 //
425 // Use context Values only for request-scoped data that transits processes and
426 // APIs, not for passing optional parameters to functions.
427 func WithValue(parent Context, key interface{}, val interface{}) Context {
428 return &valueCtx{parent, key, val}
429 }
431 // A valueCtx carries a key-value pair. It implements Value for that key and
432 // delegates all other calls to the embedded Context.
433 type valueCtx struct {
434 Context
435 key, val interface{}
436 }
438 func (c *valueCtx) String() string {
439 return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
440 }
442 func (c *valueCtx) Value(key interface{}) interface{} {
443 if c.key == key {
444 return c.val
445 }
446 return c.Context.Value(key)
447 }