blob: 02d0967818976fbcfcd85642aa8b7b6adab739a3 [file] [log] [blame]
Matt Rosencrantz5845bf12015-01-06 13:05:21 -08001package rt
2
3import (
4 "fmt"
5 "time"
6
7 _ "v.io/core/veyron/lib/stats/sysstats"
8 "v.io/core/veyron2"
9 "v.io/core/veyron2/context"
10 "v.io/core/veyron2/ipc"
11 "v.io/core/veyron2/ipc/stream"
12 "v.io/core/veyron2/naming"
13 "v.io/core/veyron2/options"
14 "v.io/core/veyron2/security"
15 "v.io/core/veyron2/vlog"
16 "v.io/core/veyron2/vtrace"
17
18 //iipc "v.io/core/veyron/runtimes/google/ipc"
19 iipc "v.io/core/veyron/runtimes/google/ipc"
20 imanager "v.io/core/veyron/runtimes/google/ipc/stream/manager"
21 "v.io/core/veyron/runtimes/google/ipc/stream/vc"
22 inaming "v.io/core/veyron/runtimes/google/naming"
23 "v.io/core/veyron/runtimes/google/naming/namespace"
24 ivtrace "v.io/core/veyron/runtimes/google/vtrace"
25)
26
27type contextKey int
28
29const (
30 streamManagerKey = contextKey(iota)
31 clientKey
32 namespaceKey
33 loggerKey
34 principalKey
35 vtraceKey
36 reservedNameKey
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -080037 profileKey
38 appCycleKey
39 listenSpecKey
Suharsh Sivakumarba563932015-01-06 15:15:50 -080040 protocolsKey
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080041)
42
43func init() {
44 veyron2.RegisterRuntime("google", &RuntimeX{})
45}
46
47// initRuntimeXContext provides compatibility between Runtime and RuntimeX.
48// It is only used during the transition between runtime and
49// RuntimeX. It populates a context with all the subparts that the
50// new interface expects to be present. In the future this work will
51// be replaced by RuntimeX.Init()
52// TODO(mattr): Remove this after the runtime->runtimex transistion.
53func (rt *vrt) initRuntimeXContext(ctx *context.T) *context.T {
54 ctx = context.WithValue(ctx, streamManagerKey, rt.sm[0])
55 ctx = context.WithValue(ctx, clientKey, rt.client)
56 ctx = context.WithValue(ctx, namespaceKey, rt.ns)
57 ctx = context.WithValue(ctx, loggerKey, vlog.Log)
58 ctx = context.WithValue(ctx, principalKey, rt.principal)
59 ctx = context.WithValue(ctx, vtraceKey, rt.traceStore)
60 return ctx
61}
62
63// RuntimeX implements the veyron2.RuntimeX interface. It is stateless.
64// Please see the interface definition for documentation of the
65// individiual methods.
66type RuntimeX struct{}
67
68// TODO(mattr): This function isn't used yet. We'll implement it later
69// in the transition.
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -080070func (*RuntimeX) Init(ctx *context.T) *context.T {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080071 // TODO(mattr): Here we need to do a bunch of one time init, like parsing flags
72 // and reading the credentials, init logging and verror, start an appcycle manager.
73 // TODO(mattr): Here we need to arrange for a long of one time cleanup
74 // when cancel is called. Dump vtrace, shotdown signalhandling, shutdownlogging,
75 // shutdown the appcyclemanager.
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -080076 return nil
Matt Rosencrantz5845bf12015-01-06 13:05:21 -080077}
78
79func (*RuntimeX) NewEndpoint(ep string) (naming.Endpoint, error) {
80 return inaming.NewEndpoint(ep)
81}
82
83func (r *RuntimeX) NewServer(ctx *context.T, opts ...ipc.ServerOpt) (ipc.Server, error) {
84 // Create a new RoutingID (and StreamManager) for each server.
85 _, sm, err := r.SetNewStreamManager(ctx)
86 if err != nil {
87 return nil, fmt.Errorf("failed to create ipc/stream/Manager: %v", err)
88 }
89
90 ns, _ := ctx.Value(namespaceKey).(naming.Namespace)
91 principal, _ := ctx.Value(principalKey).(security.Principal)
92
93 otherOpts := append([]ipc.ServerOpt{}, opts...)
94 otherOpts = append(otherOpts, vc.LocalPrincipal{principal})
95 if reserved, ok := ctx.Value(reservedNameKey).(*reservedNameDispatcher); ok {
96 otherOpts = append(otherOpts, options.ReservedNameDispatcher{reserved.dispatcher})
97 otherOpts = append(otherOpts, reserved.opts...)
98 }
99 // TODO(mattr): We used to get rt.preferredprotocols here, should we
100 // attach these to the context directly?
101
102 traceStore, _ := ctx.Value(vtraceKey).(*ivtrace.Store)
103 server, err := iipc.InternalNewServer(ctx, sm, ns, traceStore, otherOpts...)
104 if done := ctx.Done(); err == nil && done != nil {
105 // Arrange to clean up the server when the parent context is canceled.
106 // TODO(mattr): Should we actually do this? Or just have users clean
107 // their own servers up manually?
108 go func() {
109 <-done
110 server.Stop()
111 }()
112 }
113 return server, err
114}
115
116func (r *RuntimeX) setNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) {
117 rid, err := naming.NewRoutingID()
118 if err != nil {
119 return ctx, nil, err
120 }
121 sm := imanager.InternalNew(rid)
122 ctx = context.WithValue(ctx, streamManagerKey, sm)
123
124 // Arrange for the manager to shut itself down when the context is canceled.
125 if done := ctx.Done(); done != nil {
126 go func() {
127 <-done
128 sm.Shutdown()
129 }()
130 }
131
132 return ctx, sm, nil
133}
134
135func (r *RuntimeX) SetNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) {
136 newctx, sm, err := r.setNewStreamManager(ctx, opts...)
137 if err != nil {
138 return ctx, nil, err
139 }
140
141 // Create a new client since it depends on the stream manager.
142 newctx, _, err = r.SetNewClient(newctx)
143 if err != nil {
144 return ctx, nil, err
145 }
146
147 return newctx, sm, nil
148}
149
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800150func (*RuntimeX) GetStreamManager(ctx *context.T) stream.Manager {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800151 cl, _ := ctx.Value(streamManagerKey).(stream.Manager)
152 return cl
153}
154
155func (r *RuntimeX) SetPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) {
156 var err error
157 newctx := ctx
158
159 newctx = context.WithValue(newctx, principalKey, principal)
160
161 // TODO(mattr, suharshs): The stream manager holds a cache of vifs
162 // which were negotiated with the principal, so we replace it here when the
163 // principal changes. However we should negotiate the vif with a
164 // random principal and then we needn't replace this here.
165 if newctx, _, err = r.setNewStreamManager(newctx); err != nil {
166 return ctx, err
167 }
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800168 if newctx, _, err = r.setNewNamespace(newctx, r.GetNamespace(ctx).Roots()...); err != nil {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800169 return ctx, err
170 }
171 if newctx, _, err = r.SetNewClient(newctx); err != nil {
172 return ctx, err
173 }
174
175 return newctx, nil
176}
177
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800178func (*RuntimeX) GetPrincipal(ctx *context.T) security.Principal {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800179 p, _ := ctx.Value(principalKey).(security.Principal)
180 return p
181}
182
183func (*RuntimeX) SetNewClient(ctx *context.T, opts ...ipc.ClientOpt) (*context.T, ipc.Client, error) {
184 // TODO(mattr, suharshs): Currently there are a lot of things that can come in as opts.
185 // Some of them will be removed as opts and simply be pulled from the context instead
186 // these are:
187 // stream.Manager, Namespace, LocalPrincipal
188 sm, _ := ctx.Value(streamManagerKey).(stream.Manager)
189 ns, _ := ctx.Value(namespaceKey).(naming.Namespace)
190 p, _ := ctx.Value(principalKey).(security.Principal)
Suharsh Sivakumarba563932015-01-06 15:15:50 -0800191 protocols, _ := ctx.Value(protocolsKey).([]string)
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800192
193 // TODO(mattr, suharshs): Some will need to ba accessible from the
194 // client so that we can replace the client transparantly:
195 // VCSecurityLevel, PreferredProtocols
196 // Currently we are ignoring these and the settings will be lost in some cases.
197 // We should try to retrieve them from the client currently attached to the context
198 // where possible.
199 otherOpts := append([]ipc.ClientOpt{}, opts...)
200
201 // Note we always add DialTimeout, so we don't have to worry about replicating the option.
Suharsh Sivakumarba563932015-01-06 15:15:50 -0800202 otherOpts = append(otherOpts, vc.LocalPrincipal{p}, &imanager.DialTimeout{5 * time.Minute}, options.PreferredProtocols(protocols))
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800203
204 client, err := iipc.InternalNewClient(sm, ns, otherOpts...)
205 if err == nil {
206 ctx = context.WithValue(ctx, clientKey, client)
207 }
208 return ctx, client, err
209}
210
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800211func (*RuntimeX) GetClient(ctx *context.T) ipc.Client {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800212 cl, _ := ctx.Value(clientKey).(ipc.Client)
213 return cl
214}
215
216func (*RuntimeX) SetNewSpan(ctx *context.T, name string) (*context.T, vtrace.Span) {
217 return ivtrace.WithNewSpan(ctx, name)
218}
219
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800220func (*RuntimeX) GetSpan(ctx *context.T) vtrace.Span {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800221 return ivtrace.FromContext(ctx)
222}
223
224func (*RuntimeX) setNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) {
225 ns, err := namespace.New(roots...)
226 if err == nil {
227 ctx = context.WithValue(ctx, namespaceKey, ns)
228 }
229 return ctx, ns, err
230}
231
232func (r *RuntimeX) SetNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) {
233 newctx, ns, err := r.setNewNamespace(ctx, roots...)
234 if err != nil {
235 return ctx, nil, err
236 }
237
238 // Replace the client since it depends on the namespace.
239 newctx, _, err = r.SetNewClient(newctx)
240 if err != nil {
241 return ctx, nil, err
242 }
243
244 return newctx, ns, err
245}
246
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800247func (*RuntimeX) GetNamespace(ctx *context.T) naming.Namespace {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800248 ns, _ := ctx.Value(namespaceKey).(naming.Namespace)
249 return ns
250}
251
252func (*RuntimeX) SetNewLogger(ctx *context.T, name string, opts ...vlog.LoggingOpts) (*context.T, vlog.Logger, error) {
253 logger, err := vlog.NewLogger(name, opts...)
254 if err == nil {
255 ctx = context.WithValue(ctx, loggerKey, logger)
256 }
257 return ctx, logger, err
258}
259
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800260func (*RuntimeX) GetLogger(ctx *context.T) vlog.Logger {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800261 logger, _ := ctx.Value(loggerKey).(vlog.Logger)
262 return logger
263}
264
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800265func (*RuntimeX) GetVtraceStore(ctx *context.T) vtrace.Store {
Matt Rosencrantz5845bf12015-01-06 13:05:21 -0800266 traceStore, _ := ctx.Value(vtraceKey).(vtrace.Store)
267 return traceStore
268}
269
270type reservedNameDispatcher struct {
271 dispatcher ipc.Dispatcher
272 opts []ipc.ServerOpt
273}
274
275// TODO(mattr): Get this from the profile instead, then remove this
276// method from the interface.
277func (*RuntimeX) SetReservedNameDispatcher(ctx *context.T, server ipc.Dispatcher, opts ...ipc.ServerOpt) *context.T {
278 return context.WithValue(ctx, reservedNameKey, &reservedNameDispatcher{server, opts})
279}
Suharsh Sivakumarba563932015-01-06 15:15:50 -0800280
Suharsh Sivakumar033a30e2015-01-07 13:54:43 -0800281// SetProfile sets the profile used to create this runtime.
282// TODO(suharshs, mattr): Determine if this is needed by functions after the new
283// profile init function is in use. This will probably be easy to do because:
284// Name is used in tests only.
285// Platform is used for String representaions of a Profile.
286// String is unused.
287// Cleanup is used in rt.Cleanup and can probably be replaced by a cancelfunc returned
288// by the new profile initialization function.
289func (*RuntimeX) SetProfile(ctx *context.T, profile veyron2.Profile) *context.T {
290 return context.WithValue(ctx, profileKey, profile)
291}
292
293func (*RuntimeX) GetProfile(ctx *context.T) veyron2.Profile {
294 profile, _ := ctx.Value(profileKey).(veyron2.Profile)
295 return profile
296}
297
298func (*RuntimeX) SetAppCycle(ctx *context.T, appCycle veyron2.AppCycle) *context.T {
299 return context.WithValue(ctx, appCycleKey, appCycle)
300}
301
302func (*RuntimeX) GetAppCycle(ctx *context.T) veyron2.AppCycle {
303 appCycle, _ := ctx.Value(appCycleKey).(veyron2.AppCycle)
304 return appCycle
305}
306
307func (*RuntimeX) SetListenSpec(ctx *context.T, listenSpec ipc.ListenSpec) *context.T {
308 return context.WithValue(ctx, listenSpecKey, listenSpec)
309}
310
311func (*RuntimeX) GetListenSpec(ctx *context.T) ipc.ListenSpec {
312 listenSpec, _ := ctx.Value(listenSpecKey).(ipc.ListenSpec)
313 return listenSpec
314}
315
Suharsh Sivakumarba563932015-01-06 15:15:50 -0800316func (*RuntimeX) SetPreferredProtocols(ctx *context.T, protocols []string) *context.T {
317 return context.WithValue(ctx, protocolsKey, protocols)
318}