-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathwakeup_android.go
131 lines (113 loc) · 5.08 KB
/
wakeup_android.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build android
package jni
import (
"fmt"
"time"
"v.io/v23/context"
"v.io/v23/namespace"
"v.io/v23/naming"
"v.io/v23/security/access"
)
// wakeupNamespace is a namespace used by the persistent Android services
// to mount themselves in a way that they can be woken up whenever a
// client resolves their names.
//
// This namespace consists of two sub-parts:
// 1) The original namespace (OrigNS),
// 2) The mount root used for waking up the service (WakeMTRoot)
//
// Let's say the service wishes to mount itself under a relative name
// 'a/b'. (Absolute names are disallowed.) The service first mounts its
// endpoints under 'WakeMTRoot/server/a/b' and then mounts name
// 'WakeMTRoot/client/a/b' under 'OrigNS/a/b'. When the client resolves
// 'OrigNS/a/b', the name resolution will trigger resolution of
// 'WakeMTRoot/client/a/b', which in turn triggers the process of waking
// up the server.
//
// Note that we prefix mounted names by 'client' and 'server' above.
// This is needed in order to distinguish the cases of a server mounting itself
// into the mounttable (i.e., no wakeup needed) from the case of a client
// resolving a name (i.e., wakeup needed).
type wakeupNamespace struct {
wakeupMountRoot string
ns namespace.T
}
func (w *wakeupNamespace) Mount(ctx *context.T, name, server string, ttl time.Duration, opts ...naming.NamespaceOpt) error {
if naming.Rooted(name) {
return fmt.Errorf("Mount(%q): rooted names not allowed in wakeup namespace", name)
}
mountName := naming.Join(w.wakeupMountRoot, "server", name)
if err := w.ns.Mount(ctx, mountName, server, ttl, opts...); err != nil {
return err
}
// We set an infinite TTL at the original mount location as it allows us to wake up a
// server even after its mount entries have expired. (It's fine if the wakeup MT entries
// do expire.) Since entries are mounted forever, we explicitly have to clean up previous
// entries.
w.ns.Delete(ctx, name, false)
wakeupName := naming.Join(w.wakeupMountRoot, "client", name)
var zeroTTL time.Duration
return w.ns.Mount(ctx, name, wakeupName, zeroTTL, append(opts, naming.ServesMountTable(true))...)
}
func (w *wakeupNamespace) Unmount(ctx *context.T, name, server string, opts ...naming.NamespaceOpt) error {
if naming.Rooted(name) {
return fmt.Errorf("Unmount(%q): rooted names not allowed in wakeup namespace", name)
}
mountName := naming.Join(w.wakeupMountRoot, "server", name)
return w.ns.Unmount(ctx, mountName, server, opts...)
// We never unmount at the original location as it allows us to wake up a sleeping server.
}
func (w *wakeupNamespace) Delete(ctx *context.T, name string, deleteSubtree bool, opts ...naming.NamespaceOpt) error {
if naming.Rooted(name) {
return fmt.Errorf("Delete(%q): rooted names not allowed in wakeup namespace", name)
}
mountName := naming.Join(w.wakeupMountRoot, "server", name)
if err := w.ns.Delete(ctx, mountName, deleteSubtree, opts...); err != nil {
return err
}
return w.ns.Delete(ctx, name, deleteSubtree, opts...)
}
func (w *wakeupNamespace) Resolve(ctx *context.T, name string, opts ...naming.NamespaceOpt) (entry *naming.MountEntry, err error) {
return w.ns.Resolve(ctx, name, opts...)
}
func (w *wakeupNamespace) ShallowResolve(ctx *context.T, name string, opts ...naming.NamespaceOpt) (entry *naming.MountEntry, err error) {
return w.ns.ShallowResolve(ctx, name, opts...)
}
func (w *wakeupNamespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.NamespaceOpt) (entry *naming.MountEntry, err error) {
return w.ns.ResolveToMountTable(ctx, name, opts...)
}
func (w *wakeupNamespace) FlushCacheEntry(ctx *context.T, name string) bool {
if naming.Rooted(name) {
return false
}
mountName := naming.Join(w.wakeupMountRoot, "server", name)
return w.ns.FlushCacheEntry(ctx, mountName) || w.ns.FlushCacheEntry(ctx, name)
}
func (w *wakeupNamespace) CacheCtl(ctls ...naming.CacheCtl) []naming.CacheCtl {
return w.ns.CacheCtl(ctls...)
}
func (w *wakeupNamespace) Glob(ctx *context.T, pattern string, opts ...naming.NamespaceOpt) (<-chan naming.GlobReply, error) {
return w.ns.Glob(ctx, pattern, opts...)
}
func (w *wakeupNamespace) SetRoots(roots ...string) error {
return w.ns.SetRoots(roots...)
}
func (w *wakeupNamespace) Roots() []string {
return w.ns.Roots()
}
func (w *wakeupNamespace) SetPermissions(ctx *context.T, name string, perms access.Permissions, version string, opts ...naming.NamespaceOpt) error {
if naming.Rooted(name) {
return fmt.Errorf("SetPermissions(%q): rooted names not allowed in wakeup namespace", name)
}
mountName := naming.Join(w.wakeupMountRoot, "server", name)
if err := w.ns.SetPermissions(ctx, mountName, perms, version, opts...); err != nil {
return err
}
return w.ns.SetPermissions(ctx, name, perms, version, opts...)
}
func (w *wakeupNamespace) GetPermissions(ctx *context.T, name string, opts ...naming.NamespaceOpt) (perms access.Permissions, version string, err error) {
return w.ns.GetPermissions(ctx, name, opts...)
}