Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 1 | package rt |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 5 | "os" |
| 6 | "os/signal" |
| 7 | "path/filepath" |
| 8 | "strings" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 9 | "syscall" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 10 | "time" |
| 11 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 12 | "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 Presotto | d424c21 | 2015-02-25 11:05:26 -0800 | [diff] [blame] | 17 | ns "v.io/v23/naming/ns" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 18 | "v.io/v23/options" |
| 19 | "v.io/v23/security" |
| 20 | "v.io/v23/verror" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 21 | "v.io/v23/vtrace" |
Jiri Simsa | 337af23 | 2015-02-27 14:36:46 -0800 | [diff] [blame] | 22 | "v.io/x/lib/vlog" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 23 | |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 24 | "v.io/x/ref/lib/flags" |
Bogdan Caprita | 3eb7469 | 2015-03-05 09:34:18 -0800 | [diff] [blame^] | 25 | "v.io/x/ref/lib/flags/buildinfo" |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 26 | "v.io/x/ref/lib/stats" |
| 27 | _ "v.io/x/ref/lib/stats/sysstats" |
Matt Rosencrantz | dbc1be2 | 2015-02-28 15:15:49 -0800 | [diff] [blame] | 28 | 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 Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 36 | ) |
| 37 | |
| 38 | type contextKey int |
| 39 | |
| 40 | const ( |
| 41 | streamManagerKey = contextKey(iota) |
| 42 | clientKey |
| 43 | namespaceKey |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 44 | principalKey |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 45 | reservedNameKey |
Suharsh Sivakumar | 033a30e | 2015-01-07 13:54:43 -0800 | [diff] [blame] | 46 | profileKey |
| 47 | appCycleKey |
| 48 | listenSpecKey |
Suharsh Sivakumar | ba56393 | 2015-01-06 15:15:50 -0800 | [diff] [blame] | 49 | protocolsKey |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 50 | backgroundKey |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 51 | ) |
| 52 | |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 53 | type vtraceDependency struct{} |
| 54 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 55 | // Runtime implements the v23.Runtime interface. |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 56 | // Please see the interface definition for documentation of the |
| 57 | // individiual methods. |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 58 | type Runtime struct { |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 59 | deps *dependency.Graph |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 60 | } |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 61 | |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 62 | type reservedNameDispatcher struct { |
| 63 | dispatcher ipc.Dispatcher |
| 64 | opts []ipc.ServerOpt |
| 65 | } |
| 66 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 67 | func 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 Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 69 | r := &Runtime{deps: dependency.NewGraph()} |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 70 | |
Matt Rosencrantz | 97d67a9 | 2015-01-27 21:03:12 -0800 | [diff] [blame] | 71 | err := vlog.ConfigureLibraryLoggerFromFlags() |
| 72 | if err != nil { |
| 73 | return nil, nil, nil, err |
| 74 | } |
Bogdan Caprita | 3eb7469 | 2015-03-05 09:34:18 -0800 | [diff] [blame^] | 75 | // 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 Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 87 | |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 88 | // 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 Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 98 | 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 Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 106 | if len(protocols) > 0 { |
| 107 | ctx = context.WithValue(ctx, protocolsKey, protocols) |
| 108 | } |
| 109 | |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 110 | if listenSpec != nil { |
| 111 | ctx = context.WithValue(ctx, listenSpecKey, listenSpec) |
| 112 | } |
| 113 | |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 114 | // 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 Wang | ff73e1f | 2015-02-10 21:45:52 -0800 | [diff] [blame] | 127 | ctx = verror.ContextWithComponentName(ctx, filepath.Base(os.Args[0])) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 128 | |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 129 | // 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 Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 139 | ctx, err = r.setNewStreamManager(ctx) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 140 | if err != nil { |
| 141 | return nil, nil, nil, err |
| 142 | } |
| 143 | |
Matt Rosencrantz | 99cc06e | 2015-01-16 10:25:11 -0800 | [diff] [blame] | 144 | // The client we create here is incomplete (has a nil principal) and only works |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 145 | // because the agent uses anonymous unix sockets and VCSecurityNone. |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 146 | // After security is initialized we attach a real client. |
Matt Rosencrantz | 99cc06e | 2015-01-16 10:25:11 -0800 | [diff] [blame] | 147 | _, client, err := r.SetNewClient(ctx) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 148 | if err != nil { |
| 149 | return nil, nil, nil, err |
| 150 | } |
| 151 | |
| 152 | // Initialize security. |
Matt Rosencrantz | 3199588 | 2015-01-27 20:00:48 -0800 | [diff] [blame] | 153 | principal, err := initSecurity(ctx, flags.Credentials, client) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 154 | if err != nil { |
| 155 | return nil, nil, nil, err |
| 156 | } |
Suharsh Sivakumar | 5ca4664 | 2015-01-30 10:33:38 -0800 | [diff] [blame] | 157 | ctx = r.setPrincipal(ctx, principal) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 158 | |
| 159 | // Set up secure client. |
| 160 | ctx, _, err = r.SetNewClient(ctx) |
| 161 | if err != nil { |
| 162 | return nil, nil, nil, err |
| 163 | } |
| 164 | |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 165 | ctx = r.SetBackgroundContext(ctx) |
| 166 | |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 167 | return r, ctx, r.shutdown, nil |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 168 | } |
| 169 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 170 | func (r *Runtime) addChild(ctx *context.T, me interface{}, stop func(), dependsOn ...interface{}) error { |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 171 | if err := r.deps.Depend(me, dependsOn...); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 172 | stop() |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 173 | return err |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 174 | } else if done := ctx.Done(); done != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 175 | go func() { |
| 176 | <-done |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 177 | finish := r.deps.CloseAndWait(me) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 178 | stop() |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 179 | finish() |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 180 | }() |
| 181 | } |
| 182 | return nil |
| 183 | } |
| 184 | |
Matt Rosencrantz | 3199588 | 2015-01-27 20:00:48 -0800 | [diff] [blame] | 185 | func (r *Runtime) Init(ctx *context.T) error { |
| 186 | return r.initMgmt(ctx) |
| 187 | } |
| 188 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 189 | func (r *Runtime) shutdown() { |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 190 | r.deps.CloseAndWaitForAll() |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 191 | vlog.FlushLog() |
| 192 | } |
| 193 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 194 | func (r *Runtime) initSignalHandling(ctx *context.T) { |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 195 | // 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 Rosencrantz | cf714c6 | 2015-01-22 16:15:56 -0800 | [diff] [blame] | 202 | signals := make(chan os.Signal, 1) |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 203 | signal.Notify(signals, syscall.SIGHUP) |
| 204 | go func() { |
| 205 | for { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 206 | sig, ok := <-signals |
| 207 | if !ok { |
| 208 | break |
| 209 | } |
| 210 | vlog.Infof("Received signal %v", sig) |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 211 | } |
| 212 | }() |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 213 | r.addChild(ctx, signals, func() { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 214 | signal.Stop(signals) |
| 215 | close(signals) |
| 216 | }) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 217 | } |
| 218 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 219 | func (*Runtime) NewEndpoint(ep string) (naming.Endpoint, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 220 | return inaming.NewEndpoint(ep) |
| 221 | } |
| 222 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 223 | func (r *Runtime) NewServer(ctx *context.T, opts ...ipc.ServerOpt) (ipc.Server, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 224 | // Create a new RoutingID (and StreamManager) for each server. |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 225 | sm, err := newStreamManager() |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 226 | 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 Presotto | d424c21 | 2015-02-25 11:05:26 -0800 | [diff] [blame] | 230 | ns, _ := ctx.Value(namespaceKey).(ns.Namespace) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 231 | principal, _ := ctx.Value(principalKey).(security.Principal) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 232 | client, _ := ctx.Value(clientKey).(ipc.Client) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 233 | |
| 234 | otherOpts := append([]ipc.ServerOpt{}, opts...) |
| 235 | otherOpts = append(otherOpts, vc.LocalPrincipal{principal}) |
| 236 | if reserved, ok := ctx.Value(reservedNameKey).(*reservedNameDispatcher); ok { |
Suharsh Sivakumar | d7a6519 | 2015-01-27 22:57:15 -0800 | [diff] [blame] | 237 | otherOpts = append(otherOpts, iipc.ReservedNameDispatcher{reserved.dispatcher}) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 238 | otherOpts = append(otherOpts, reserved.opts...) |
| 239 | } |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 240 | if protocols, ok := ctx.Value(protocolsKey).([]string); ok { |
| 241 | otherOpts = append(otherOpts, iipc.PreferredServerResolveProtocols(protocols)) |
| 242 | } |
Suharsh Sivakumar | 77357d7 | 2015-02-21 22:14:20 -0800 | [diff] [blame] | 243 | |
| 244 | if !hasServerBlessingsOpt(opts) && principal != nil { |
| 245 | otherOpts = append(otherOpts, options.ServerBlessings{principal.BlessingStore().Default()}) |
| 246 | } |
Suharsh Sivakumar | af99c97 | 2015-01-28 15:28:49 -0800 | [diff] [blame] | 247 | server, err := iipc.InternalNewServer(ctx, sm, ns, r.GetClient(ctx), otherOpts...) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 248 | if err != nil { |
| 249 | return nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 250 | } |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 251 | stop := func() { |
| 252 | if err := server.Stop(); err != nil { |
| 253 | vlog.Errorf("A server could not be stopped: %v", err) |
| 254 | } |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 255 | sm.Shutdown() |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 256 | } |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 257 | if err = r.addChild(ctx, server, stop, client, vtraceDependency{}); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 258 | return nil, err |
| 259 | } |
| 260 | return server, nil |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 261 | } |
| 262 | |
Suharsh Sivakumar | 77357d7 | 2015-02-21 22:14:20 -0800 | [diff] [blame] | 263 | func 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 Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 272 | func newStreamManager() (stream.Manager, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 273 | rid, err := naming.NewRoutingID() |
| 274 | if err != nil { |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 275 | return nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 276 | } |
| 277 | sm := imanager.InternalNew(rid) |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 278 | return sm, nil |
| 279 | } |
| 280 | |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 281 | func (r *Runtime) setNewStreamManager(ctx *context.T) (*context.T, error) { |
| 282 | sm, err := newStreamManager() |
| 283 | if err != nil { |
| 284 | return nil, err |
| 285 | } |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 286 | newctx := context.WithValue(ctx, streamManagerKey, sm) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 287 | if err = r.addChild(ctx, sm, sm.Shutdown); err != nil { |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 288 | return ctx, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 289 | } |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 290 | return newctx, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 291 | } |
| 292 | |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 293 | func (r *Runtime) SetNewStreamManager(ctx *context.T) (*context.T, error) { |
| 294 | newctx, err := r.setNewStreamManager(ctx) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 295 | if err != nil { |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 296 | return ctx, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | // Create a new client since it depends on the stream manager. |
| 300 | newctx, _, err = r.SetNewClient(newctx) |
| 301 | if err != nil { |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 302 | return ctx, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 303 | } |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 304 | return newctx, nil |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 305 | } |
| 306 | |
Suharsh Sivakumar | 5ca4664 | 2015-01-30 10:33:38 -0800 | [diff] [blame] | 307 | func (*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 Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 315 | func (r *Runtime) SetPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 316 | var err error |
| 317 | newctx := ctx |
| 318 | |
Suharsh Sivakumar | 5ca4664 | 2015-01-30 10:33:38 -0800 | [diff] [blame] | 319 | newctx = r.setPrincipal(ctx, principal) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 320 | |
Suharsh Sivakumar | af862a5 | 2015-02-04 13:50:47 -0800 | [diff] [blame] | 321 | if newctx, err = r.setNewStreamManager(newctx); err != nil { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 322 | return ctx, err |
| 323 | } |
Suharsh Sivakumar | 033a30e | 2015-01-07 13:54:43 -0800 | [diff] [blame] | 324 | if newctx, _, err = r.setNewNamespace(newctx, r.GetNamespace(ctx).Roots()...); err != nil { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 325 | 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 Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 334 | func (*Runtime) GetPrincipal(ctx *context.T) security.Principal { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 335 | p, _ := ctx.Value(principalKey).(security.Principal) |
| 336 | return p |
| 337 | } |
| 338 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 339 | func (r *Runtime) SetNewClient(ctx *context.T, opts ...ipc.ClientOpt) (*context.T, ipc.Client, error) { |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 340 | otherOpts := append([]ipc.ClientOpt{}, opts...) |
| 341 | |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 342 | sm, _ := ctx.Value(streamManagerKey).(stream.Manager) |
David Why Use Two When One Will Do Presotto | d424c21 | 2015-02-25 11:05:26 -0800 | [diff] [blame] | 343 | ns, _ := ctx.Value(namespaceKey).(ns.Namespace) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 344 | p, _ := ctx.Value(principalKey).(security.Principal) |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 345 | otherOpts = append(otherOpts, vc.LocalPrincipal{p}, &imanager.DialTimeout{5 * time.Minute}) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 346 | |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 347 | if protocols, ok := ctx.Value(protocolsKey).([]string); ok { |
Suharsh Sivakumar | d7a6519 | 2015-01-27 22:57:15 -0800 | [diff] [blame] | 348 | otherOpts = append(otherOpts, iipc.PreferredProtocols(protocols)) |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 349 | } |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 350 | |
| 351 | client, err := iipc.InternalNewClient(sm, ns, otherOpts...) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 352 | if err != nil { |
| 353 | return ctx, nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 354 | } |
Matt Rosencrantz | 1932912 | 2015-01-23 22:18:49 -0800 | [diff] [blame] | 355 | newctx := context.WithValue(ctx, clientKey, client) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 356 | if err = r.addChild(ctx, client, client.Close, sm, vtraceDependency{}); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 357 | return ctx, nil, err |
| 358 | } |
| 359 | return newctx, client, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 360 | } |
| 361 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 362 | func (*Runtime) GetClient(ctx *context.T) ipc.Client { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 363 | cl, _ := ctx.Value(clientKey).(ipc.Client) |
| 364 | return cl |
| 365 | } |
| 366 | |
David Why Use Two When One Will Do Presotto | d424c21 | 2015-02-25 11:05:26 -0800 | [diff] [blame] | 367 | func (r *Runtime) setNewNamespace(ctx *context.T, roots ...string) (*context.T, ns.Namespace, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 368 | ns, err := namespace.New(roots...) |
Matt Rosencrantz | 001644e | 2015-01-29 14:24:48 -0800 | [diff] [blame] | 369 | |
| 370 | if oldNS := r.GetNamespace(ctx); oldNS != nil { |
| 371 | ns.CacheCtl(oldNS.CacheCtl()...) |
| 372 | } |
| 373 | |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 374 | 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 Presotto | d424c21 | 2015-02-25 11:05:26 -0800 | [diff] [blame] | 380 | func (r *Runtime) SetNewNamespace(ctx *context.T, roots ...string) (*context.T, ns.Namespace, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 381 | 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 Presotto | d424c21 | 2015-02-25 11:05:26 -0800 | [diff] [blame] | 395 | func (*Runtime) GetNamespace(ctx *context.T) ns.Namespace { |
| 396 | ns, _ := ctx.Value(namespaceKey).(ns.Namespace) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 397 | return ns |
| 398 | } |
| 399 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 400 | func (*Runtime) GetAppCycle(ctx *context.T) v23.AppCycle { |
| 401 | appCycle, _ := ctx.Value(appCycleKey).(v23.AppCycle) |
Suharsh Sivakumar | 033a30e | 2015-01-07 13:54:43 -0800 | [diff] [blame] | 402 | return appCycle |
| 403 | } |
| 404 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 405 | func (*Runtime) GetListenSpec(ctx *context.T) ipc.ListenSpec { |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 406 | listenSpec, _ := ctx.Value(listenSpecKey).(*ipc.ListenSpec) |
| 407 | return *listenSpec |
Suharsh Sivakumar | ac9feed | 2015-01-08 10:58:37 -0800 | [diff] [blame] | 408 | } |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 409 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 410 | func (*Runtime) SetBackgroundContext(ctx *context.T) *context.T { |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 411 | // 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 Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 418 | func (*Runtime) GetBackgroundContext(ctx *context.T) *context.T { |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 419 | 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 | } |