wsprd: Pass state changes on the mountstate of a server to the JS
console
This also has a bug fix in the vdl generator where enums were generated
incorrectly.
MultiPart: 1/2
Change-Id: Iee5fe16ae89af312fa3862b2ec1dc521e17035f9
diff --git a/lib/vdl/codegen/javascript/gen.go b/lib/vdl/codegen/javascript/gen.go
index 6403d4d..454ac25 100644
--- a/lib/vdl/codegen/javascript/gen.go
+++ b/lib/vdl/codegen/javascript/gen.go
@@ -336,6 +336,17 @@
return false
}
+func hasEnums(pkg *compile.Package) bool {
+ for _, file := range pkg.Files {
+ for _, def := range file.TypeDefs {
+ if def.Type.Kind() == vdl.Enum {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func generateSystemImports(data data) string {
res := "var vdl = require('"
packagePrefix := ""
@@ -358,7 +369,7 @@
}
}
- if hasConsts(data.Pkg) {
+ if hasConsts(data.Pkg) || hasEnums(data.Pkg) {
if data.PathToCoreJS != "" {
res += "var canonicalize = require('" + packagePrefix + "/vdl/canonicalize');\n"
} else {
diff --git a/services/wsprd/app/app.go b/services/wsprd/app/app.go
index b71db40..435f7ad 100644
--- a/services/wsprd/app/app.go
+++ b/services/wsprd/app/app.go
@@ -750,3 +750,14 @@
blessings, _ := clientCall.RemoteBlessings()
return blessings, nil
}
+
+func (c *Controller) SendLogMessage(level lib.LogLevel, msg string) error {
+ c.Lock()
+ defer c.Unlock()
+ id := c.lastGeneratedId
+ c.lastGeneratedId += 2
+ return c.writerCreator(id).Send(lib.ResponseLog, lib.LogMessage{
+ Level: level,
+ Message: msg,
+ })
+}
diff --git a/services/wsprd/app/mock_jsServer_test.go b/services/wsprd/app/mock_jsServer_test.go
index c8ca3f7..55bbd30 100644
--- a/services/wsprd/app/mock_jsServer_test.go
+++ b/services/wsprd/app/mock_jsServer_test.go
@@ -65,6 +65,9 @@
}
m.receivedResponse = vdl.ValueOf(msg)
return nil
+ case lib.ResponseLog:
+ m.flowCount += 2
+ return nil
}
return fmt.Errorf("Unknown message type: %d", responseType)
}
diff --git a/services/wsprd/lib/writer.go b/services/wsprd/lib/writer.go
index f6d60a1..a1ccecc 100644
--- a/services/wsprd/lib/writer.go
+++ b/services/wsprd/lib/writer.go
@@ -16,6 +16,7 @@
ResponseAuthRequest = 6
ResponseCancel = 7
ResponseValidate = 8 // Request to validate caveats.
+ ResponseLog = 9 // Sends a message to be logged.
)
type Response struct {
diff --git a/services/wsprd/lib/writer.vdl b/services/wsprd/lib/writer.vdl
index 7197042..ce94e21 100644
--- a/services/wsprd/lib/writer.vdl
+++ b/services/wsprd/lib/writer.vdl
@@ -12,3 +12,13 @@
Err error
TraceResponse vtrace.Response
}
+
+type LogLevel enum {
+ Info
+ Error
+}
+
+type LogMessage struct {
+ Level LogLevel
+ Message string
+}
diff --git a/services/wsprd/lib/writer.vdl.go b/services/wsprd/lib/writer.vdl.go
index 483ec60..e2845a9 100644
--- a/services/wsprd/lib/writer.vdl.go
+++ b/services/wsprd/lib/writer.vdl.go
@@ -9,6 +9,7 @@
import (
// VDL system imports
+ "fmt"
"v.io/v23/vdl"
// VDL user imports
@@ -27,6 +28,65 @@
}) {
}
+type LogLevel int
+
+const (
+ LogLevelInfo LogLevel = iota
+ LogLevelError
+)
+
+// LogLevelAll holds all labels for LogLevel.
+var LogLevelAll = [...]LogLevel{LogLevelInfo, LogLevelError}
+
+// LogLevelFromString creates a LogLevel from a string label.
+func LogLevelFromString(label string) (x LogLevel, err error) {
+ err = x.Set(label)
+ return
+}
+
+// Set assigns label to x.
+func (x *LogLevel) Set(label string) error {
+ switch label {
+ case "Info", "info":
+ *x = LogLevelInfo
+ return nil
+ case "Error", "error":
+ *x = LogLevelError
+ return nil
+ }
+ *x = -1
+ return fmt.Errorf("unknown label %q in lib.LogLevel", label)
+}
+
+// String returns the string label of x.
+func (x LogLevel) String() string {
+ switch x {
+ case LogLevelInfo:
+ return "Info"
+ case LogLevelError:
+ return "Error"
+ }
+ return ""
+}
+
+func (LogLevel) __VDLReflect(struct {
+ Name string "v.io/x/ref/services/wsprd/lib.LogLevel"
+ Enum struct{ Info, Error string }
+}) {
+}
+
+type LogMessage struct {
+ Level LogLevel
+ Message string
+}
+
+func (LogMessage) __VDLReflect(struct {
+ Name string "v.io/x/ref/services/wsprd/lib.LogMessage"
+}) {
+}
+
func init() {
vdl.Register((*ServerRpcReply)(nil))
+ vdl.Register((*LogLevel)(nil))
+ vdl.Register((*LogMessage)(nil))
}
diff --git a/services/wsprd/rpc/server/server.go b/services/wsprd/rpc/server/server.go
index c7b8c80..8fe0131 100644
--- a/services/wsprd/rpc/server/server.go
+++ b/services/wsprd/rpc/server/server.go
@@ -63,6 +63,8 @@
FlowHandler
HandleStore
+ SendLogMessage(level lib.LogLevel, msg string) error
+
Context() *context.T
}
@@ -110,6 +112,10 @@
outstandingAuthRequests map[int32]chan error
outstandingValidationRequests map[int32]chan []error
+
+ // statusClose will be closed when the server is shutting down, this will
+ // cause the status poller to exit.
+ statusClose chan struct{}
}
func NewServer(id uint32, listenSpec *rpc.ListenSpec, helper ServerHelper) (*Server, error) {
@@ -506,6 +512,37 @@
}
}
+func (s *Server) readStatus() {
+ // A map of names to the last error message sent.
+ lastErrors := map[string]string{}
+ for {
+ status := s.server.Status()
+ for _, mountStatus := range status.Mounts {
+ var errMsg string
+ if mountStatus.LastMountErr != nil {
+ errMsg = mountStatus.LastMountErr.Error()
+ }
+ mountName := mountStatus.Name
+ if lastMessage, ok := lastErrors[mountName]; !ok || errMsg != lastMessage {
+ if errMsg == "" {
+ s.helper.SendLogMessage(
+ lib.LogLevelInfo, "serve: "+mountName+" successfully mounted ")
+ } else {
+ s.helper.SendLogMessage(
+ lib.LogLevelError, "serve: "+mountName+" failed with: "+errMsg)
+ }
+ }
+ lastErrors[mountName] = errMsg
+ }
+ select {
+ case <-time.After(10 * time.Second):
+ continue
+ case <-s.statusClose:
+ return
+ }
+ }
+}
+
func (s *Server) Serve(name string) error {
s.serverStateLock.Lock()
defer s.serverStateLock.Unlock()
@@ -524,6 +561,8 @@
if err := s.server.ServeDispatcher(name, s.dispatcher); err != nil {
return err
}
+ s.statusClose = make(chan struct{}, 1)
+ go s.readStatus()
return nil
}
@@ -644,6 +683,9 @@
}
s.serverStateLock.Lock()
+ if s.statusClose != nil {
+ close(s.statusClose)
+ }
if s.dispatcher != nil {
s.dispatcher.Cleanup()
}