blob: fceb78e27521fd96af68a5daf5f25d2f1fd87d04 [file] [log] [blame]
Matt Rosencrantz5845bf12015-01-06 13:05:21 -08001package rt
2
3import (
4 "fmt"
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -08005 "os"
6 "os/signal"
7 "path/filepath"
8 "strings"
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -08009 "syscall"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080010 "time"
11
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080012 "v.io/core/veyron2"
13 "v.io/core/veyron2/context"
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -080014 "v.io/core/veyron2/i18n"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080015 "v.io/core/veyron2/ipc"
16 "v.io/core/veyron2/ipc/stream"
17 "v.io/core/veyron2/naming"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080018 "v.io/core/veyron2/security"
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -080019 "v.io/core/veyron2/verror2"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080020 "v.io/core/veyron2/vlog"
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -080021 "v.io/core/veyron2/vtrace"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080022
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -080023 "v.io/core/veyron/lib/flags"
24 _ "v.io/core/veyron/lib/stats/sysstats"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080025 iipc "v.io/core/veyron/runtimes/google/ipc"
26 imanager "v.io/core/veyron/runtimes/google/ipc/stream/manager"
27 "v.io/core/veyron/runtimes/google/ipc/stream/vc"
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -080028 "v.io/core/veyron/runtimes/google/lib/dependency"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080029 inaming "v.io/core/veyron/runtimes/google/naming"
30 "v.io/core/veyron/runtimes/google/naming/namespace"
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -080031 ivtrace "v.io/core/veyron/runtimes/google/vtrace"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080032)
33
34type contextKey int
35
36const (
37 streamManagerKey = contextKey(iota)
38 clientKey
39 namespaceKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080040 principalKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080041 reservedNameKey
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -080042 profileKey
43 appCycleKey
44 listenSpecKey
Suharsh Sivakumarba563932015-01-06 15:15:50 -080045 protocolsKey
Matt Rosencrantz3838c552015-01-15 13:04:53 -080046 backgroundKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080047)
48
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -080049type vtraceDependency struct{}
50
Matt Rosencrantzba470a52015-01-26 13:36:13 -080051// Runtime implements the veyron2.Runtime interface.
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080052// Please see the interface definition for documentation of the
53// individiual methods.
Matt Rosencrantzba470a52015-01-26 13:36:13 -080054type Runtime struct {
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -080055 deps *dependency.Graph
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -080056}
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080057
Suharsh Sivakumard5049b72015-01-21 14:11:35 -080058type reservedNameDispatcher struct {
59 dispatcher ipc.Dispatcher
60 opts []ipc.ServerOpt
61}
62
Suharsh Sivakumar79bec0e2015-01-27 18:59:36 -080063// TODO(mattr,suharshs): Decide if Options would be better than this.
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080064func Init(ctx *context.T, appCycle veyron2.AppCycle, protocols []string, listenSpec *ipc.ListenSpec, flags flags.RuntimeFlags,
Matt Rosencrantzba470a52015-01-26 13:36:13 -080065 reservedDispatcher ipc.Dispatcher, dispatcherOpts ...ipc.ServerOpt) (*Runtime, *context.T, veyron2.Shutdown, error) {
66 r := &Runtime{deps: dependency.NewGraph()}
Matt Rosencrantz96d952a2015-01-15 09:18:38 -080067
Matt Rosencrantz97d67a92015-01-27 21:03:12 -080068 err := vlog.ConfigureLibraryLoggerFromFlags()
69 if err != nil {
70 return nil, nil, nil, err
71 }
Matt Rosencrantz96d952a2015-01-15 09:18:38 -080072
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -080073 // Setup the initial trace.
74 ctx, err = ivtrace.Init(ctx, flags.Vtrace)
75 if err != nil {
76 return nil, nil, nil, err
77 }
78 ctx, _ = vtrace.SetNewTrace(ctx)
79 r.addChild(ctx, vtraceDependency{}, func() {
80 vtrace.FormatTraces(os.Stderr, vtrace.GetStore(ctx).TraceRecords(), nil)
81 })
82
Suharsh Sivakumard5049b72015-01-21 14:11:35 -080083 if reservedDispatcher != nil {
84 ctx = context.WithValue(ctx, reservedNameKey, &reservedNameDispatcher{reservedDispatcher, dispatcherOpts})
85 }
86
87 if appCycle != nil {
88 ctx = context.WithValue(ctx, appCycleKey, appCycle)
89 }
90
Matt Rosencrantz96d952a2015-01-15 09:18:38 -080091 if len(protocols) > 0 {
92 ctx = context.WithValue(ctx, protocolsKey, protocols)
93 }
94
Suharsh Sivakumard5049b72015-01-21 14:11:35 -080095 if listenSpec != nil {
96 ctx = context.WithValue(ctx, listenSpecKey, listenSpec)
97 }
98
Matt Rosencrantz96d952a2015-01-15 09:18:38 -080099 // Setup i18n.
100 ctx = i18n.ContextWithLangID(ctx, i18n.LangIDFromEnv())
101 if len(flags.I18nCatalogue) != 0 {
102 cat := i18n.Cat()
103 for _, filename := range strings.Split(flags.I18nCatalogue, ",") {
104 err := cat.MergeFromFile(filename)
105 if err != nil {
106 fmt.Fprintf(os.Stderr, "%s: i18n: error reading i18n catalogue file %q: %s\n", os.Args[0], filename, err)
107 }
108 }
109 }
110
111 // Setup the program name.
112 ctx = verror2.ContextWithComponentName(ctx, filepath.Base(os.Args[0]))
113
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800114 // Enable signal handling.
115 r.initSignalHandling(ctx)
116
117 // Set the initial namespace.
118 ctx, _, err = r.setNewNamespace(ctx, flags.NamespaceRoots...)
119 if err != nil {
120 return nil, nil, nil, err
121 }
122
123 // Set the initial stream manager.
124 ctx, _, err = r.setNewStreamManager(ctx)
125 if err != nil {
126 return nil, nil, nil, err
127 }
128
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -0800129 // The client we create here is incomplete (has a nil principal) and only works
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800130 // because the agent uses anonymous unix sockets and VCSecurityNone.
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800131 // After security is initialized we attach a real client.
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -0800132 _, client, err := r.SetNewClient(ctx)
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800133 if err != nil {
134 return nil, nil, nil, err
135 }
136
137 // Initialize security.
Matt Rosencrantz31995882015-01-27 20:00:48 -0800138 principal, err := initSecurity(ctx, flags.Credentials, client)
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800139 if err != nil {
140 return nil, nil, nil, err
141 }
142 ctx = context.WithValue(ctx, principalKey, principal)
143
144 // Set up secure client.
145 ctx, _, err = r.SetNewClient(ctx)
146 if err != nil {
147 return nil, nil, nil, err
148 }
149
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800150 ctx = r.SetBackgroundContext(ctx)
151
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800152 // TODO(suharshs,mattr): Go through the rt.Cleanup function and make sure everything
153 // gets cleaned up.
154
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800155 return r, ctx, r.shutdown, nil
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800156}
157
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800158func (r *Runtime) addChild(ctx *context.T, me interface{}, stop func(), dependsOn ...interface{}) error {
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800159 if err := r.deps.Depend(me, dependsOn...); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800160 stop()
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800161 return err
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800162 } else if done := ctx.Done(); done != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800163 go func() {
164 <-done
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800165 finish := r.deps.CloseAndWait(me)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800166 stop()
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800167 finish()
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800168 }()
169 }
170 return nil
171}
172
Matt Rosencrantz31995882015-01-27 20:00:48 -0800173func (r *Runtime) Init(ctx *context.T) error {
174 return r.initMgmt(ctx)
175}
176
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800177func (r *Runtime) shutdown() {
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800178 r.deps.CloseAndWaitForAll()
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800179 vlog.FlushLog()
180}
181
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800182func (r *Runtime) initSignalHandling(ctx *context.T) {
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -0800183 // TODO(caprita): Given that our device manager implementation is to
184 // kill all child apps when the device manager dies, we should
185 // enable SIGHUP on apps by default.
186
187 // Automatically handle SIGHUP to prevent applications started as
188 // daemons from being killed. The developer can choose to still listen
189 // on SIGHUP and take a different action if desired.
Matt Rosencrantzcf714c62015-01-22 16:15:56 -0800190 signals := make(chan os.Signal, 1)
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -0800191 signal.Notify(signals, syscall.SIGHUP)
192 go func() {
193 for {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800194 sig, ok := <-signals
195 if !ok {
196 break
197 }
198 vlog.Infof("Received signal %v", sig)
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -0800199 }
200 }()
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800201 r.addChild(ctx, signals, func() {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800202 signal.Stop(signals)
203 close(signals)
204 })
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800205}
206
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800207func (*Runtime) NewEndpoint(ep string) (naming.Endpoint, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800208 return inaming.NewEndpoint(ep)
209}
210
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800211func (r *Runtime) NewServer(ctx *context.T, opts ...ipc.ServerOpt) (ipc.Server, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800212 // Create a new RoutingID (and StreamManager) for each server.
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800213 sm, err := newStreamManager()
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800214 if err != nil {
215 return nil, fmt.Errorf("failed to create ipc/stream/Manager: %v", err)
216 }
217
218 ns, _ := ctx.Value(namespaceKey).(naming.Namespace)
219 principal, _ := ctx.Value(principalKey).(security.Principal)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800220 client, _ := ctx.Value(clientKey).(ipc.Client)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800221
222 otherOpts := append([]ipc.ServerOpt{}, opts...)
223 otherOpts = append(otherOpts, vc.LocalPrincipal{principal})
224 if reserved, ok := ctx.Value(reservedNameKey).(*reservedNameDispatcher); ok {
Suharsh Sivakumard7a65192015-01-27 22:57:15 -0800225 otherOpts = append(otherOpts, iipc.ReservedNameDispatcher{reserved.dispatcher})
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800226 otherOpts = append(otherOpts, reserved.opts...)
227 }
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800228 if protocols, ok := ctx.Value(protocolsKey).([]string); ok {
229 otherOpts = append(otherOpts, iipc.PreferredServerResolveProtocols(protocols))
230 }
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -0800231 server, err := iipc.InternalNewServer(ctx, sm, ns, r.GetClient(ctx), otherOpts...)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800232 if err != nil {
233 return nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800234 }
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800235 stop := func() {
236 if err := server.Stop(); err != nil {
237 vlog.Errorf("A server could not be stopped: %v", err)
238 }
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800239 sm.Shutdown()
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800240 }
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800241 if err = r.addChild(ctx, server, stop, client, vtraceDependency{}); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800242 return nil, err
243 }
244 return server, nil
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800245}
246
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800247func newStreamManager(opts ...stream.ManagerOpt) (stream.Manager, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800248 rid, err := naming.NewRoutingID()
249 if err != nil {
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800250 return nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800251 }
252 sm := imanager.InternalNew(rid)
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800253 return sm, nil
254}
255
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800256func (r *Runtime) setNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) {
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800257 sm, err := newStreamManager(opts...)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800258 newctx := context.WithValue(ctx, streamManagerKey, sm)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800259 if err = r.addChild(ctx, sm, sm.Shutdown); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800260 return ctx, nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800261 }
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800262 return newctx, sm, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800263}
264
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800265func (r *Runtime) SetNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800266 newctx, sm, err := r.setNewStreamManager(ctx, opts...)
267 if err != nil {
268 return ctx, nil, err
269 }
270
271 // Create a new client since it depends on the stream manager.
272 newctx, _, err = r.SetNewClient(newctx)
273 if err != nil {
274 return ctx, nil, err
275 }
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800276 return newctx, sm, nil
277}
278
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800279func (*Runtime) GetStreamManager(ctx *context.T) stream.Manager {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800280 cl, _ := ctx.Value(streamManagerKey).(stream.Manager)
281 return cl
282}
283
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800284func (r *Runtime) SetPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800285 var err error
286 newctx := ctx
287
288 newctx = context.WithValue(newctx, principalKey, principal)
289
290 // TODO(mattr, suharshs): The stream manager holds a cache of vifs
291 // which were negotiated with the principal, so we replace it here when the
292 // principal changes. However we should negotiate the vif with a
293 // random principal and then we needn't replace this here.
294 if newctx, _, err = r.setNewStreamManager(newctx); err != nil {
295 return ctx, err
296 }
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800297 if newctx, _, err = r.setNewNamespace(newctx, r.GetNamespace(ctx).Roots()...); err != nil {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800298 return ctx, err
299 }
300 if newctx, _, err = r.SetNewClient(newctx); err != nil {
301 return ctx, err
302 }
303
304 return newctx, nil
305}
306
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800307func (*Runtime) GetPrincipal(ctx *context.T) security.Principal {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800308 p, _ := ctx.Value(principalKey).(security.Principal)
309 return p
310}
311
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800312func (r *Runtime) SetNewClient(ctx *context.T, opts ...ipc.ClientOpt) (*context.T, ipc.Client, error) {
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800313 otherOpts := append([]ipc.ClientOpt{}, opts...)
314
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800315 // TODO(mattr, suharshs): Currently there are a lot of things that can come in as opts.
316 // Some of them will be removed as opts and simply be pulled from the context instead
317 // these are:
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800318 // stream.Manager, Namespace, LocalPrincipal, preferred protocols.
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800319 sm, _ := ctx.Value(streamManagerKey).(stream.Manager)
320 ns, _ := ctx.Value(namespaceKey).(naming.Namespace)
321 p, _ := ctx.Value(principalKey).(security.Principal)
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800322 otherOpts = append(otherOpts, vc.LocalPrincipal{p}, &imanager.DialTimeout{5 * time.Minute})
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800323
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800324 if protocols, ok := ctx.Value(protocolsKey).([]string); ok {
Suharsh Sivakumard7a65192015-01-27 22:57:15 -0800325 otherOpts = append(otherOpts, iipc.PreferredProtocols(protocols))
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800326 }
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800327
328 client, err := iipc.InternalNewClient(sm, ns, otherOpts...)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800329 if err != nil {
330 return ctx, nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800331 }
Matt Rosencrantz19329122015-01-23 22:18:49 -0800332 newctx := context.WithValue(ctx, clientKey, client)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800333 if err = r.addChild(ctx, client, client.Close, sm, vtraceDependency{}); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800334 return ctx, nil, err
335 }
336 return newctx, client, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800337}
338
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800339func (*Runtime) GetClient(ctx *context.T) ipc.Client {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800340 cl, _ := ctx.Value(clientKey).(ipc.Client)
341 return cl
342}
343
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800344func (*Runtime) setNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800345 ns, err := namespace.New(roots...)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800346 // TODO(mattr): Copy cache settings.
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800347 if err == nil {
348 ctx = context.WithValue(ctx, namespaceKey, ns)
349 }
350 return ctx, ns, err
351}
352
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800353func (r *Runtime) SetNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800354 newctx, ns, err := r.setNewNamespace(ctx, roots...)
355 if err != nil {
356 return ctx, nil, err
357 }
358
359 // Replace the client since it depends on the namespace.
360 newctx, _, err = r.SetNewClient(newctx)
361 if err != nil {
362 return ctx, nil, err
363 }
364
365 return newctx, ns, err
366}
367
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800368func (*Runtime) GetNamespace(ctx *context.T) naming.Namespace {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800369 ns, _ := ctx.Value(namespaceKey).(naming.Namespace)
370 return ns
371}
372
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800373func (*Runtime) GetAppCycle(ctx *context.T) veyron2.AppCycle {
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800374 appCycle, _ := ctx.Value(appCycleKey).(veyron2.AppCycle)
375 return appCycle
376}
377
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800378func (*Runtime) GetListenSpec(ctx *context.T) ipc.ListenSpec {
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800379 listenSpec, _ := ctx.Value(listenSpecKey).(*ipc.ListenSpec)
380 return *listenSpec
Suharsh Sivakumarac9feed2015-01-08 10:58:37 -0800381}
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800382
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800383func (*Runtime) SetBackgroundContext(ctx *context.T) *context.T {
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800384 // Note we add an extra context with a nil value here.
385 // This prevents users from travelling back through the
386 // chain of background contexts.
387 ctx = context.WithValue(ctx, backgroundKey, nil)
388 return context.WithValue(ctx, backgroundKey, ctx)
389}
390
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800391func (*Runtime) GetBackgroundContext(ctx *context.T) *context.T {
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800392 bctx, _ := ctx.Value(backgroundKey).(*context.T)
393 if bctx == nil {
394 // There should always be a background context. If we don't find
395 // it, that means that the user passed us the background context
396 // in hopes of following the chain. Instead we just give them
397 // back what they sent in, which is correct.
398 return ctx
399 }
400 return bctx
401}