blob: 332aef30cec7d2f497ff6f443c907221480ac64e [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
Jiri Simsa6ac95222015-02-23 16:11:49 -080012 "v.io/v23"
13 "v.io/v23/context"
14 "v.io/v23/i18n"
15 "v.io/v23/ipc"
16 "v.io/v23/naming"
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -080017 ns "v.io/v23/naming/ns"
Jiri Simsa6ac95222015-02-23 16:11:49 -080018 "v.io/v23/options"
19 "v.io/v23/security"
20 "v.io/v23/verror"
Jiri Simsa6ac95222015-02-23 16:11:49 -080021 "v.io/v23/vtrace"
Jiri Simsa337af232015-02-27 14:36:46 -080022 "v.io/x/lib/vlog"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080023
Jiri Simsaffceefa2015-02-28 11:03:34 -080024 "v.io/x/ref/lib/flags"
Bogdan Caprita3eb74692015-03-05 09:34:18 -080025 "v.io/x/ref/lib/flags/buildinfo"
Jiri Simsaffceefa2015-02-28 11:03:34 -080026 "v.io/x/ref/lib/stats"
27 _ "v.io/x/ref/lib/stats/sysstats"
Matt Rosencrantzdbc1be22015-02-28 15:15:49 -080028 iipc "v.io/x/ref/profiles/internal/ipc"
29 "v.io/x/ref/profiles/internal/ipc/stream"
30 imanager "v.io/x/ref/profiles/internal/ipc/stream/manager"
31 "v.io/x/ref/profiles/internal/ipc/stream/vc"
32 "v.io/x/ref/profiles/internal/lib/dependency"
33 inaming "v.io/x/ref/profiles/internal/naming"
34 "v.io/x/ref/profiles/internal/naming/namespace"
35 ivtrace "v.io/x/ref/profiles/internal/vtrace"
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080036)
37
38type contextKey int
39
40const (
41 streamManagerKey = contextKey(iota)
42 clientKey
43 namespaceKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080044 principalKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080045 reservedNameKey
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -080046 profileKey
47 appCycleKey
48 listenSpecKey
Suharsh Sivakumarba563932015-01-06 15:15:50 -080049 protocolsKey
Matt Rosencrantz3838c552015-01-15 13:04:53 -080050 backgroundKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080051)
52
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -080053type vtraceDependency struct{}
54
Jiri Simsa6ac95222015-02-23 16:11:49 -080055// Runtime implements the v23.Runtime interface.
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080056// Please see the interface definition for documentation of the
57// individiual methods.
Matt Rosencrantzba470a52015-01-26 13:36:13 -080058type Runtime struct {
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -080059 deps *dependency.Graph
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -080060}
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080061
Suharsh Sivakumard5049b72015-01-21 14:11:35 -080062type reservedNameDispatcher struct {
63 dispatcher ipc.Dispatcher
64 opts []ipc.ServerOpt
65}
66
Jiri Simsa6ac95222015-02-23 16:11:49 -080067func Init(ctx *context.T, appCycle v23.AppCycle, protocols []string, listenSpec *ipc.ListenSpec, flags flags.RuntimeFlags,
68 reservedDispatcher ipc.Dispatcher, dispatcherOpts ...ipc.ServerOpt) (*Runtime, *context.T, v23.Shutdown, error) {
Matt Rosencrantzba470a52015-01-26 13:36:13 -080069 r := &Runtime{deps: dependency.NewGraph()}
Matt Rosencrantz96d952a2015-01-15 09:18:38 -080070
Matt Rosencrantz97d67a92015-01-27 21:03:12 -080071 err := vlog.ConfigureLibraryLoggerFromFlags()
72 if err != nil {
73 return nil, nil, nil, err
74 }
Bogdan Caprita3eb74692015-03-05 09:34:18 -080075 // We want to print out buildinfo only into the log files, to avoid
76 // spamming stderr, see #1246.
77 //
78 // TODO(caprita): We should add it to the log file header information;
79 // since that requires changes to the llog and vlog packages, for now we
80 // condition printing of buildinfo on having specified an explicit
81 // log_dir for the program. It's a hack, but it gets us the buildinfo
82 // fo device manager-run apps and avoids it for command-lines, which is
83 // a good enough approximation.
84 if vlog.Log.LogDir() != os.TempDir() {
85 vlog.Infof("Binary info: %s", buildinfo.Info())
86 }
Matt Rosencrantz96d952a2015-01-15 09:18:38 -080087
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -080088 // Setup the initial trace.
89 ctx, err = ivtrace.Init(ctx, flags.Vtrace)
90 if err != nil {
91 return nil, nil, nil, err
92 }
93 ctx, _ = vtrace.SetNewTrace(ctx)
94 r.addChild(ctx, vtraceDependency{}, func() {
95 vtrace.FormatTraces(os.Stderr, vtrace.GetStore(ctx).TraceRecords(), nil)
96 })
97
Suharsh Sivakumard5049b72015-01-21 14:11:35 -080098 if reservedDispatcher != nil {
99 ctx = context.WithValue(ctx, reservedNameKey, &reservedNameDispatcher{reservedDispatcher, dispatcherOpts})
100 }
101
102 if appCycle != nil {
103 ctx = context.WithValue(ctx, appCycleKey, appCycle)
104 }
105
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800106 if len(protocols) > 0 {
107 ctx = context.WithValue(ctx, protocolsKey, protocols)
108 }
109
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800110 if listenSpec != nil {
111 ctx = context.WithValue(ctx, listenSpecKey, listenSpec)
112 }
113
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800114 // Setup i18n.
115 ctx = i18n.ContextWithLangID(ctx, i18n.LangIDFromEnv())
116 if len(flags.I18nCatalogue) != 0 {
117 cat := i18n.Cat()
118 for _, filename := range strings.Split(flags.I18nCatalogue, ",") {
119 err := cat.MergeFromFile(filename)
120 if err != nil {
121 fmt.Fprintf(os.Stderr, "%s: i18n: error reading i18n catalogue file %q: %s\n", os.Args[0], filename, err)
122 }
123 }
124 }
125
126 // Setup the program name.
Todd Wangff73e1f2015-02-10 21:45:52 -0800127 ctx = verror.ContextWithComponentName(ctx, filepath.Base(os.Args[0]))
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800128
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800129 // Enable signal handling.
130 r.initSignalHandling(ctx)
131
132 // Set the initial namespace.
133 ctx, _, err = r.setNewNamespace(ctx, flags.NamespaceRoots...)
134 if err != nil {
135 return nil, nil, nil, err
136 }
137
138 // Set the initial stream manager.
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800139 ctx, err = r.setNewStreamManager(ctx)
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800140 if err != nil {
141 return nil, nil, nil, err
142 }
143
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -0800144 // The client we create here is incomplete (has a nil principal) and only works
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800145 // because the agent uses anonymous unix sockets and VCSecurityNone.
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800146 // After security is initialized we attach a real client.
Matt Rosencrantz99cc06e2015-01-16 10:25:11 -0800147 _, client, err := r.SetNewClient(ctx)
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800148 if err != nil {
149 return nil, nil, nil, err
150 }
151
152 // Initialize security.
Matt Rosencrantz31995882015-01-27 20:00:48 -0800153 principal, err := initSecurity(ctx, flags.Credentials, client)
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800154 if err != nil {
155 return nil, nil, nil, err
156 }
Suharsh Sivakumar5ca46642015-01-30 10:33:38 -0800157 ctx = r.setPrincipal(ctx, principal)
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800158
159 // Set up secure client.
160 ctx, _, err = r.SetNewClient(ctx)
161 if err != nil {
162 return nil, nil, nil, err
163 }
164
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800165 ctx = r.SetBackgroundContext(ctx)
166
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800167 return r, ctx, r.shutdown, nil
Matt Rosencrantz96d952a2015-01-15 09:18:38 -0800168}
169
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800170func (r *Runtime) addChild(ctx *context.T, me interface{}, stop func(), dependsOn ...interface{}) error {
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800171 if err := r.deps.Depend(me, dependsOn...); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800172 stop()
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800173 return err
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800174 } else if done := ctx.Done(); done != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800175 go func() {
176 <-done
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800177 finish := r.deps.CloseAndWait(me)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800178 stop()
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800179 finish()
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800180 }()
181 }
182 return nil
183}
184
Matt Rosencrantz31995882015-01-27 20:00:48 -0800185func (r *Runtime) Init(ctx *context.T) error {
186 return r.initMgmt(ctx)
187}
188
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800189func (r *Runtime) shutdown() {
Matt Rosencrantz5dbfbef2015-01-26 12:40:56 -0800190 r.deps.CloseAndWaitForAll()
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800191 vlog.FlushLog()
192}
193
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800194func (r *Runtime) initSignalHandling(ctx *context.T) {
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -0800195 // TODO(caprita): Given that our device manager implementation is to
196 // kill all child apps when the device manager dies, we should
197 // enable SIGHUP on apps by default.
198
199 // Automatically handle SIGHUP to prevent applications started as
200 // daemons from being killed. The developer can choose to still listen
201 // on SIGHUP and take a different action if desired.
Matt Rosencrantzcf714c62015-01-22 16:15:56 -0800202 signals := make(chan os.Signal, 1)
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -0800203 signal.Notify(signals, syscall.SIGHUP)
204 go func() {
205 for {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800206 sig, ok := <-signals
207 if !ok {
208 break
209 }
210 vlog.Infof("Received signal %v", sig)
Suharsh Sivakumar628a8ee2015-01-14 11:38:56 -0800211 }
212 }()
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800213 r.addChild(ctx, signals, func() {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800214 signal.Stop(signals)
215 close(signals)
216 })
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800217}
218
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800219func (*Runtime) NewEndpoint(ep string) (naming.Endpoint, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800220 return inaming.NewEndpoint(ep)
221}
222
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800223func (r *Runtime) NewServer(ctx *context.T, opts ...ipc.ServerOpt) (ipc.Server, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800224 // Create a new RoutingID (and StreamManager) for each server.
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800225 sm, err := newStreamManager()
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800226 if err != nil {
227 return nil, fmt.Errorf("failed to create ipc/stream/Manager: %v", err)
228 }
229
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800230 ns, _ := ctx.Value(namespaceKey).(ns.Namespace)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800231 principal, _ := ctx.Value(principalKey).(security.Principal)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800232 client, _ := ctx.Value(clientKey).(ipc.Client)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800233
234 otherOpts := append([]ipc.ServerOpt{}, opts...)
235 otherOpts = append(otherOpts, vc.LocalPrincipal{principal})
236 if reserved, ok := ctx.Value(reservedNameKey).(*reservedNameDispatcher); ok {
Suharsh Sivakumard7a65192015-01-27 22:57:15 -0800237 otherOpts = append(otherOpts, iipc.ReservedNameDispatcher{reserved.dispatcher})
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800238 otherOpts = append(otherOpts, reserved.opts...)
239 }
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800240 if protocols, ok := ctx.Value(protocolsKey).([]string); ok {
241 otherOpts = append(otherOpts, iipc.PreferredServerResolveProtocols(protocols))
242 }
Suharsh Sivakumar77357d72015-02-21 22:14:20 -0800243
244 if !hasServerBlessingsOpt(opts) && principal != nil {
245 otherOpts = append(otherOpts, options.ServerBlessings{principal.BlessingStore().Default()})
246 }
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -0800247 server, err := iipc.InternalNewServer(ctx, sm, ns, r.GetClient(ctx), otherOpts...)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800248 if err != nil {
249 return nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800250 }
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800251 stop := func() {
252 if err := server.Stop(); err != nil {
253 vlog.Errorf("A server could not be stopped: %v", err)
254 }
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800255 sm.Shutdown()
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800256 }
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800257 if err = r.addChild(ctx, server, stop, client, vtraceDependency{}); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800258 return nil, err
259 }
260 return server, nil
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800261}
262
Suharsh Sivakumar77357d72015-02-21 22:14:20 -0800263func hasServerBlessingsOpt(opts []ipc.ServerOpt) bool {
264 for _, o := range opts {
265 if _, ok := o.(options.ServerBlessings); ok {
266 return true
267 }
268 }
269 return false
270}
271
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800272func newStreamManager() (stream.Manager, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800273 rid, err := naming.NewRoutingID()
274 if err != nil {
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800275 return nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800276 }
277 sm := imanager.InternalNew(rid)
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800278 return sm, nil
279}
280
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800281func (r *Runtime) setNewStreamManager(ctx *context.T) (*context.T, error) {
282 sm, err := newStreamManager()
283 if err != nil {
284 return nil, err
285 }
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800286 newctx := context.WithValue(ctx, streamManagerKey, sm)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800287 if err = r.addChild(ctx, sm, sm.Shutdown); err != nil {
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800288 return ctx, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800289 }
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800290 return newctx, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800291}
292
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800293func (r *Runtime) SetNewStreamManager(ctx *context.T) (*context.T, error) {
294 newctx, err := r.setNewStreamManager(ctx)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800295 if err != nil {
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800296 return ctx, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800297 }
298
299 // Create a new client since it depends on the stream manager.
300 newctx, _, err = r.SetNewClient(newctx)
301 if err != nil {
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800302 return ctx, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800303 }
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800304 return newctx, nil
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800305}
306
Suharsh Sivakumar5ca46642015-01-30 10:33:38 -0800307func (*Runtime) setPrincipal(ctx *context.T, principal security.Principal) *context.T {
308 // We uniquely identity a principal with "security/principal/<publicKey>"
309 principalName := "security/principal/" + principal.PublicKey().String()
310 stats.NewStringFunc(principalName+"/blessingstore", principal.BlessingStore().DebugString)
311 stats.NewStringFunc(principalName+"/blessingroots", principal.Roots().DebugString)
312 return context.WithValue(ctx, principalKey, principal)
313}
314
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800315func (r *Runtime) SetPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800316 var err error
317 newctx := ctx
318
Suharsh Sivakumar5ca46642015-01-30 10:33:38 -0800319 newctx = r.setPrincipal(ctx, principal)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800320
Suharsh Sivakumaraf862a52015-02-04 13:50:47 -0800321 if newctx, err = r.setNewStreamManager(newctx); err != nil {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800322 return ctx, err
323 }
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800324 if newctx, _, err = r.setNewNamespace(newctx, r.GetNamespace(ctx).Roots()...); err != nil {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800325 return ctx, err
326 }
327 if newctx, _, err = r.SetNewClient(newctx); err != nil {
328 return ctx, err
329 }
330
331 return newctx, nil
332}
333
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800334func (*Runtime) GetPrincipal(ctx *context.T) security.Principal {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800335 p, _ := ctx.Value(principalKey).(security.Principal)
336 return p
337}
338
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800339func (r *Runtime) SetNewClient(ctx *context.T, opts ...ipc.ClientOpt) (*context.T, ipc.Client, error) {
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800340 otherOpts := append([]ipc.ClientOpt{}, opts...)
341
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800342 sm, _ := ctx.Value(streamManagerKey).(stream.Manager)
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800343 ns, _ := ctx.Value(namespaceKey).(ns.Namespace)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800344 p, _ := ctx.Value(principalKey).(security.Principal)
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800345 otherOpts = append(otherOpts, vc.LocalPrincipal{p}, &imanager.DialTimeout{5 * time.Minute})
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800346
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800347 if protocols, ok := ctx.Value(protocolsKey).([]string); ok {
Suharsh Sivakumard7a65192015-01-27 22:57:15 -0800348 otherOpts = append(otherOpts, iipc.PreferredProtocols(protocols))
Matt Rosencrantz9db8bc32015-01-13 09:01:55 -0800349 }
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800350
351 client, err := iipc.InternalNewClient(sm, ns, otherOpts...)
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800352 if err != nil {
353 return ctx, nil, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800354 }
Matt Rosencrantz19329122015-01-23 22:18:49 -0800355 newctx := context.WithValue(ctx, clientKey, client)
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800356 if err = r.addChild(ctx, client, client.Close, sm, vtraceDependency{}); err != nil {
Matt Rosencrantzaeed5d52015-01-14 15:18:34 -0800357 return ctx, nil, err
358 }
359 return newctx, client, err
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800360}
361
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800362func (*Runtime) GetClient(ctx *context.T) ipc.Client {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800363 cl, _ := ctx.Value(clientKey).(ipc.Client)
364 return cl
365}
366
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800367func (r *Runtime) setNewNamespace(ctx *context.T, roots ...string) (*context.T, ns.Namespace, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800368 ns, err := namespace.New(roots...)
Matt Rosencrantz001644e2015-01-29 14:24:48 -0800369
370 if oldNS := r.GetNamespace(ctx); oldNS != nil {
371 ns.CacheCtl(oldNS.CacheCtl()...)
372 }
373
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800374 if err == nil {
375 ctx = context.WithValue(ctx, namespaceKey, ns)
376 }
377 return ctx, ns, err
378}
379
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800380func (r *Runtime) SetNewNamespace(ctx *context.T, roots ...string) (*context.T, ns.Namespace, error) {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800381 newctx, ns, err := r.setNewNamespace(ctx, roots...)
382 if err != nil {
383 return ctx, nil, err
384 }
385
386 // Replace the client since it depends on the namespace.
387 newctx, _, err = r.SetNewClient(newctx)
388 if err != nil {
389 return ctx, nil, err
390 }
391
392 return newctx, ns, err
393}
394
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800395func (*Runtime) GetNamespace(ctx *context.T) ns.Namespace {
396 ns, _ := ctx.Value(namespaceKey).(ns.Namespace)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800397 return ns
398}
399
Jiri Simsa6ac95222015-02-23 16:11:49 -0800400func (*Runtime) GetAppCycle(ctx *context.T) v23.AppCycle {
401 appCycle, _ := ctx.Value(appCycleKey).(v23.AppCycle)
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800402 return appCycle
403}
404
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800405func (*Runtime) GetListenSpec(ctx *context.T) ipc.ListenSpec {
Suharsh Sivakumard5049b72015-01-21 14:11:35 -0800406 listenSpec, _ := ctx.Value(listenSpecKey).(*ipc.ListenSpec)
407 return *listenSpec
Suharsh Sivakumarac9feed2015-01-08 10:58:37 -0800408}
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800409
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800410func (*Runtime) SetBackgroundContext(ctx *context.T) *context.T {
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800411 // Note we add an extra context with a nil value here.
412 // This prevents users from travelling back through the
413 // chain of background contexts.
414 ctx = context.WithValue(ctx, backgroundKey, nil)
415 return context.WithValue(ctx, backgroundKey, ctx)
416}
417
Matt Rosencrantzba470a52015-01-26 13:36:13 -0800418func (*Runtime) GetBackgroundContext(ctx *context.T) *context.T {
Matt Rosencrantz3838c552015-01-15 13:04:53 -0800419 bctx, _ := ctx.Value(backgroundKey).(*context.T)
420 if bctx == nil {
421 // There should always be a background context. If we don't find
422 // it, that means that the user passed us the background context
423 // in hopes of following the chain. Instead we just give them
424 // back what they sent in, which is correct.
425 return ctx
426 }
427 return bctx
428}