diff options
Diffstat (limited to 'adapter')
-rw-r--r-- | adapter/socketclient/socketclient.go | 51 | ||||
-rw-r--r-- | adapter/vppapiclient/vppapiclient.go | 31 |
2 files changed, 69 insertions, 13 deletions
diff --git a/adapter/socketclient/socketclient.go b/adapter/socketclient/socketclient.go index eec4fd0..4c576c3 100644 --- a/adapter/socketclient/socketclient.go +++ b/adapter/socketclient/socketclient.go @@ -7,10 +7,13 @@ import ( "io" "net" "os" + "path/filepath" "strings" "sync" "time" + "github.com/fsnotify/fsnotify" + "github.com/lunixbochs/struc" logger "github.com/sirupsen/logrus" @@ -31,6 +34,10 @@ var ( ConnectTimeout = time.Second * 3 DisconnectTimeout = time.Second + // MaxWaitReady defines maximum duration before waiting for socket file + // times out + MaxWaitReady = time.Second * 15 + Debug = os.Getenv("DEBUG_GOVPP_SOCK") != "" DebugMsgIds = os.Getenv("DEBUG_GOVPP_SOCKMSG") != "" @@ -72,9 +79,47 @@ func nilCallback(msgID uint16, data []byte) { Log.Warnf("no callback set, dropping message: ID=%v len=%d", msgID, len(data)) } -func (*vppClient) WaitReady() error { - // TODO: add watcher for socket file? - return nil +// WaitReady checks socket file existence and waits for it if necessary +func (c *vppClient) WaitReady() error { + // check if file at the path already exists + if _, err := os.Stat(c.sockAddr); err == nil { + return nil + } else if os.IsExist(err) { + return err + } + + // if not, watch for it + watcher, err := fsnotify.NewWatcher() + if err != nil { + return err + } + defer func() { + if err := watcher.Close(); err != nil { + Log.Errorf("failed to close file watcher: %v", err) + } + }() + + // start watching directory + if err := watcher.Add(filepath.Dir(c.sockAddr)); err != nil { + return err + } + + for { + select { + case <-time.After(MaxWaitReady): + return fmt.Errorf("waiting for socket file timed out (%s)", MaxWaitReady) + case e := <-watcher.Errors: + return e + case ev := <-watcher.Events: + Log.Debugf("watcher event: %+v", ev) + if ev.Name == c.sockAddr { + if (ev.Op & fsnotify.Create) == fsnotify.Create { + // socket was created, we are ready + return nil + } + } + } + } } func (c *vppClient) SetMsgCallback(cb adapter.MsgCallback) { diff --git a/adapter/vppapiclient/vppapiclient.go b/adapter/vppapiclient/vppapiclient.go index cac8c71..f637060 100644 --- a/adapter/vppapiclient/vppapiclient.go +++ b/adapter/vppapiclient/vppapiclient.go @@ -78,12 +78,19 @@ import ( "os" "path/filepath" "reflect" + "time" "unsafe" "git.fd.io/govpp.git/adapter" "github.com/fsnotify/fsnotify" ) +var ( + // MaxWaitReady defines maximum duration before waiting for shared memory + // segment times out + MaxWaitReady = time.Second * 15 +) + const ( // shmDir is a directory where shared memory is supposed to be created. shmDir = "/dev/shm/" @@ -181,16 +188,15 @@ func (a *vppClient) SetMsgCallback(cb adapter.MsgCallback) { // WaitReady blocks until shared memory for sending // binary api calls is present on the file system. func (a *vppClient) WaitReady() error { - var path string - // join the path to the shared memory segment + var path string if a.shmPrefix == "" { path = filepath.Join(shmDir, vppShmFile) } else { path = filepath.Join(shmDir, a.shmPrefix+"-"+vppShmFile) } - // check if file at the path exists + // check if file at the path already exists if _, err := os.Stat(path); err == nil { // file exists, we are ready return nil @@ -205,21 +211,26 @@ func (a *vppClient) WaitReady() error { } defer watcher.Close() + // start watching directory if err := watcher.Add(shmDir); err != nil { return err } for { - ev := <-watcher.Events - if ev.Name == path { - if (ev.Op & fsnotify.Create) == fsnotify.Create { - // file was created, we are ready - break + select { + case <-time.After(MaxWaitReady): + return fmt.Errorf("waiting for shared memory segment timed out (%s)", MaxWaitReady) + case e := <-watcher.Errors: + return e + case ev := <-watcher.Events: + if ev.Name == path { + if (ev.Op & fsnotify.Create) == fsnotify.Create { + // file was created, we are ready + return nil + } } } } - - return nil } //export go_msg_callback |