summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Fabry <ofabry@cisco.com>2017-11-28 19:53:14 +0100
committerOndrej Fabry <ofabry@cisco.com>2017-11-28 19:53:14 +0100
commit67482a4f8c3a3a7cf17b4edf82e61c28b318ffd9 (patch)
treef08519f399f345439bd3b3cfd4f61c1c63e34889
parent3f1edad4e6ba0a7876750aea55507fae14d8badf (diff)
Add WaitReady to VppAdapter
- this fixes issue with mocked adapter during AsyncConnect Change-Id: I952025fec865422f9e83cec9383d96f79a639c90 Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
-rw-r--r--adapter/adapter.go3
-rw-r--r--adapter/mock/mock_adapter.go5
-rw-r--r--adapter/vppapiclient/empty_adapter.go4
-rw-r--r--adapter/vppapiclient/vppapiclient_adapter.go49
-rw-r--r--cmd/binapi-generator/generator_test.go4
-rw-r--r--core/core.go61
6 files changed, 72 insertions, 54 deletions
diff --git a/adapter/adapter.go b/adapter/adapter.go
index 2843d2c..d8f29c9 100644
--- a/adapter/adapter.go
+++ b/adapter/adapter.go
@@ -30,4 +30,7 @@ type VppAdapter interface {
// SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from VPP.
SetMsgCallback(func(context uint32, msgId uint16, data []byte))
+
+ // WaitReady returns func which waits until adapter is ready.
+ WaitReady() func() error
}
diff --git a/adapter/mock/mock_adapter.go b/adapter/mock/mock_adapter.go
index 8c88030..f85f17d 100644
--- a/adapter/mock/mock_adapter.go
+++ b/adapter/mock/mock_adapter.go
@@ -294,6 +294,11 @@ func (a *VppAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data [
a.callback = cb
}
+// WaitReady mocks waiting for VPP
+func (a *VppAdapter) WaitReady() func() error {
+ return func() error { return nil }
+}
+
// MockReply stores a message to be returned when the next request comes. It is a FIFO queue - multiple replies
// can be pushed into it, the first one will be popped when some request comes.
// Using of this method automatically switches the mock into th useRepliesQueue mode.
diff --git a/adapter/vppapiclient/empty_adapter.go b/adapter/vppapiclient/empty_adapter.go
index 14f804d..7249864 100644
--- a/adapter/vppapiclient/empty_adapter.go
+++ b/adapter/vppapiclient/empty_adapter.go
@@ -50,3 +50,7 @@ func (a *vppAPIClientAdapter) SendMsg(clientID uint32, data []byte) error {
func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) {
// no op
}
+
+func (a *vppAPIClientAdapter) WaitReady() func() error {
+ return func() error { return nil }
+}
diff --git a/adapter/vppapiclient/vppapiclient_adapter.go b/adapter/vppapiclient/vppapiclient_adapter.go
index 74f0118..dfdd973 100644
--- a/adapter/vppapiclient/vppapiclient_adapter.go
+++ b/adapter/vppapiclient/vppapiclient_adapter.go
@@ -79,10 +79,21 @@ import "C"
import (
"errors"
"fmt"
+ "os"
"reflect"
"unsafe"
"git.fd.io/govpp.git/adapter"
+ "github.com/fsnotify/fsnotify"
+)
+
+const (
+ // watchedFolder is a folder where vpp's shared memory is supposed to be created.
+ // File system events are monitored in this folder.
+ watchedFolder = "/dev/shm/"
+ // watchedFile is a name of the file in the watchedFolder. Once the file is present
+ // the vpp is ready to accept a new connection.
+ watchedFile = watchedFolder + "vpe-api"
)
// vppAPIClientAdapter is the opaque context of the adapter.
@@ -139,6 +150,44 @@ func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint1
a.callback = cb
}
+// WaitReady returns func which blocks until shared memory
+// for sending bin api calls is present on the file system.
+func (a *vppAPIClientAdapter) WaitReady() func() error {
+ return func() error {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ return err
+ }
+ defer watcher.Close()
+
+ err = watcher.Add(watchedFolder)
+ if err != nil {
+ return err
+ }
+
+ if fileExists(watchedFile) {
+ return nil
+ }
+
+ for {
+ ev := <-watcher.Events
+ if ev.Name == watchedFile && (ev.Op&fsnotify.Create) == fsnotify.Create {
+ break
+ }
+ }
+ return nil
+ }
+}
+
+func fileExists(name string) bool {
+ if _, err := os.Stat(name); err != nil {
+ if os.IsNotExist(err) {
+ return false
+ }
+ }
+ return true
+}
+
//export go_msg_callback
func go_msg_callback(msgID C.uint16_t, context C.uint32_t, data unsafe.Pointer, size C.size_t) {
// convert unsafe.Pointer to byte slice
diff --git a/cmd/binapi-generator/generator_test.go b/cmd/binapi-generator/generator_test.go
index c7d89ce..a42e794 100644
--- a/cmd/binapi-generator/generator_test.go
+++ b/cmd/binapi-generator/generator_test.go
@@ -245,7 +245,7 @@ func TestGenerateMessageFieldTypes(t *testing.T) {
for j := 0; j < types.At(i).Len(); j++ {
field := types.At(i).At(j)
if jsongo.TypeArray == field.GetType() {
- err := processMessageField(testCtx, &fields, field, otherMessage)
+ err := processMessageField(testCtx, &fields, field, false)
Expect(err).ShouldNot(HaveOccurred())
Expect(fields[j-1]).To(BeEquivalentTo(expectedTypes[j-1]))
}
@@ -282,7 +282,7 @@ func TestGenerateMessageFieldMessages(t *testing.T) {
specificFieldName == "client_index" || specificFieldName == "context" {
continue
}
- err := processMessageField(testCtx, &fields, field, requestMessage)
+ err := processMessageField(testCtx, &fields, field, false)
Expect(err).ShouldNot(HaveOccurred())
Expect(fields[customIndex]).To(BeEquivalentTo(expectedTypes[customIndex]))
customIndex++
diff --git a/core/core.go b/core/core.go
index a045e60..c254214 100644
--- a/core/core.go
+++ b/core/core.go
@@ -28,7 +28,6 @@ import (
"git.fd.io/govpp.git/adapter"
"git.fd.io/govpp.git/api"
"git.fd.io/govpp.git/core/bin_api/vpe"
- "github.com/fsnotify/fsnotify"
)
const (
@@ -54,15 +53,6 @@ const (
Disconnected = iota
)
-const (
- // watchedFolder is a folder where vpp's shared memory is supposed to be created.
- // File system events are monitored in this folder.
- watchedFolder = "/dev/shm/"
- // watchedFile is a name of the file in the watchedFolder. Once the file is present
- // the vpp is ready to accept a new connection.
- watchedFile = watchedFolder + "vpe-api"
-)
-
// ConnectionEvent is a notification about change in the VPP connection state.
type ConnectionEvent struct {
// Timestamp holds the time when the event has been generated.
@@ -197,10 +187,13 @@ func newConnection(vppAdapter adapter.VppAdapter) (*Connection, error) {
return nil, errors.New("only one connection per process is supported")
}
- conn = &Connection{vpp: vppAdapter, codec: &MsgCodec{}}
- conn.channels = make(map[uint32]*api.Channel)
- conn.msgIDs = make(map[string]uint16)
- conn.notifSubscriptions = make(map[uint16][]*api.NotifSubscription)
+ conn = &Connection{
+ vpp: vppAdapter,
+ codec: &MsgCodec{},
+ channels: make(map[uint32]*api.Channel),
+ msgIDs: make(map[string]uint16),
+ notifSubscriptions: make(map[uint16][]*api.NotifSubscription),
+ }
conn.vpp.SetMsgCallback(msgCallback)
return conn, nil
@@ -235,50 +228,14 @@ func (c *Connection) disconnectVPP() {
}
}
-func fileExists(name string) bool {
- if _, err := os.Stat(name); err != nil {
- if os.IsNotExist(err) {
- return false
- }
- }
- return true
-}
-
-// waitForVpp blocks until shared memory for sending bin api calls
-// is present on the file system.
-func waitForVpp() error {
- watcher, err := fsnotify.NewWatcher()
- if err != nil {
- return err
- }
- defer watcher.Close()
-
- err = watcher.Add(watchedFolder)
- if err != nil {
- return err
- }
-
- if fileExists(watchedFile) {
- return nil
- }
-
- for {
- ev := <-watcher.Events
- if ev.Name == watchedFile && (ev.Op&fsnotify.Create) == fsnotify.Create {
- break
- }
- }
- return nil
-}
-
// connectLoop attempts to connect to VPP until it succeeds.
// Then it continues with healthCheckLoop.
func (c *Connection) connectLoop(connChan chan ConnectionEvent) {
// loop until connected
+ waitForVpp := c.vpp.WaitReady()
for {
waitForVpp()
- err := c.connectVPP()
- if err == nil {
+ if err := c.connectVPP(); err == nil {
// signal connected event
connChan <- ConnectionEvent{Timestamp: time.Now(), State: Connected}
break