From 3b7bdf68c6152a5815cebe1ed98ca8a9b46609f1 Mon Sep 17 00:00:00 2001 From: Chris Hung Date: Thu, 8 Oct 2020 20:48:56 +0800 Subject: [PATCH] refactor(sdk): release lock after discovery complete Add a wrapper function to call discovery.Discovery() and release the lock when call completed so that developer will not be forced to push something to deviceCh to release the lock fix #609 Signed-off-by: Chris Hung --- internal/autodiscovery/autodiscovery.go | 3 +- internal/autodiscovery/discovery.go | 41 ++++++++++++++++++++ internal/controller/restfuncs.go | 4 +- internal/handler/control.go | 49 ------------------------ internal/v2/controller/http/discovery.go | 11 +++++- pkg/service/async.go | 4 +- 6 files changed, 55 insertions(+), 57 deletions(-) create mode 100644 internal/autodiscovery/discovery.go diff --git a/internal/autodiscovery/autodiscovery.go b/internal/autodiscovery/autodiscovery.go index eadf414eb..2d781b695 100644 --- a/internal/autodiscovery/autodiscovery.go +++ b/internal/autodiscovery/autodiscovery.go @@ -12,7 +12,6 @@ import ( "time" "github.com/edgexfoundry/device-sdk-go/internal/container" - "github.com/edgexfoundry/device-sdk-go/internal/handler" bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/bootstrap/container" "github.com/edgexfoundry/go-mod-bootstrap/bootstrap/startup" "github.com/edgexfoundry/go-mod-bootstrap/di" @@ -53,7 +52,7 @@ func BootstrapHandler( return case <-time.After(duration): lc.Debug("Auto-discovery triggered") - handler.DiscoveryHandler(nil, discovery, lc) + DiscoveryWrapper(discovery, lc) } } }() diff --git a/internal/autodiscovery/discovery.go b/internal/autodiscovery/discovery.go new file mode 100644 index 000000000..5df93998b --- /dev/null +++ b/internal/autodiscovery/discovery.go @@ -0,0 +1,41 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- +// +// Copyright (C) 2020 IOTech Ltd +// +// SPDX-License-Identifier: Apache-2.0 + +package autodiscovery + +import ( + "fmt" + "sync" + + dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models" + "github.com/edgexfoundry/go-mod-core-contracts/clients/logger" +) + +type discoveryLocker struct { + busy bool + mux sync.Mutex +} + +var locker discoveryLocker + +func DiscoveryWrapper(discovery dsModels.ProtocolDiscovery, lc logger.LoggingClient) { + locker.mux.Lock() + if locker.busy { + lc.Info("another device discovery process is currently running") + locker.mux.Unlock() + return + } + locker.busy = true + locker.mux.Unlock() + + lc.Info(fmt.Sprintf("device discovery triggered")) + discovery.Discover() + + // ReleaseLock + locker.mux.Lock() + locker.busy = false + locker.mux.Unlock() +} diff --git a/internal/controller/restfuncs.go b/internal/controller/restfuncs.go index 446c3e5ba..a93051890 100644 --- a/internal/controller/restfuncs.go +++ b/internal/controller/restfuncs.go @@ -14,6 +14,7 @@ import ( "net/http" "runtime" + "github.com/edgexfoundry/device-sdk-go/internal/autodiscovery" "github.com/edgexfoundry/device-sdk-go/internal/common" "github.com/edgexfoundry/device-sdk-go/internal/container" "github.com/edgexfoundry/device-sdk-go/internal/handler" @@ -73,7 +74,8 @@ func (c *RestController) discoveryFunc(w http.ResponseWriter, req *http.Request) return } - handler.DiscoveryHandler(w, discovery, c.LoggingClient) + go autodiscovery.DiscoveryWrapper(discovery, c.LoggingClient) + w.WriteHeader(http.StatusAccepted) //status=202 } func (c *RestController) transformFunc(w http.ResponseWriter, req *http.Request) { diff --git a/internal/handler/control.go b/internal/handler/control.go index e2a3b3034..7a40d0c51 100644 --- a/internal/handler/control.go +++ b/internal/handler/control.go @@ -9,61 +9,12 @@ package handler import ( "fmt" - "io" - "net/http" - "sync" "github.com/edgexfoundry/device-sdk-go/internal/common" - "github.com/edgexfoundry/device-sdk-go/pkg/models" "github.com/edgexfoundry/go-mod-core-contracts/clients/logger" - "github.com/google/uuid" ) -type discoveryLocker struct { - busy bool - id string - mux sync.Mutex -} - -var locker discoveryLocker - func TransformHandler(requestMap map[string]string, lc logger.LoggingClient) (map[string]string, common.AppError) { lc.Info(fmt.Sprintf("service: transform request: transformData: %s", requestMap["transformData"])) return requestMap, nil } - -func DiscoveryHandler(w http.ResponseWriter, discovery models.ProtocolDiscovery, lc logger.LoggingClient) { - locker.mux.Lock() - if locker.id == "" { - locker.id = uuid.New().String() - } - locker.mux.Unlock() - - if w != nil { - msg := fmt.Sprintf("Discovery triggered or already running, id = %s", locker.id) - w.WriteHeader(http.StatusAccepted) //status=202 - _, _ = io.WriteString(w, msg) - } - - locker.mux.Lock() - defer locker.mux.Unlock() - if locker.busy { - lc.Info(fmt.Sprintf("Device discovery process is running, id = %s", locker.id)) - return - } - locker.busy = true - lc.Info(fmt.Sprintf("Device discovery triggered")) - - go discovery.Discover() -} - -func ReleaseLock() string { - var id string - locker.mux.Lock() - id = locker.id - locker.id = "" - locker.busy = false - locker.mux.Unlock() - - return id -} diff --git a/internal/v2/controller/http/discovery.go b/internal/v2/controller/http/discovery.go index 7004e20a3..0014c9ea3 100644 --- a/internal/v2/controller/http/discovery.go +++ b/internal/v2/controller/http/discovery.go @@ -1,11 +1,17 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- +// +// Copyright (C) 2020 IOTech Ltd +// +// SPDX-License-Identifier: Apache-2.0 + package http import ( "net/http" + "github.com/edgexfoundry/device-sdk-go/internal/autodiscovery" sdkCommon "github.com/edgexfoundry/device-sdk-go/internal/common" "github.com/edgexfoundry/device-sdk-go/internal/container" - "github.com/edgexfoundry/device-sdk-go/internal/handler" edgexErr "github.com/edgexfoundry/go-mod-core-contracts/errors" ) @@ -31,5 +37,6 @@ func (c *V2HttpController) Discovery(writer http.ResponseWriter, request *http.R return } - handler.DiscoveryHandler(writer, discovery, c.lc) + go autodiscovery.DiscoveryWrapper(discovery, c.lc) + c.sendResponse(writer, request, sdkCommon.APIV2DiscoveryRoute, nil, http.StatusAccepted) } diff --git a/pkg/service/async.go b/pkg/service/async.go index ebd38bcc3..13bc878b9 100644 --- a/pkg/service/async.go +++ b/pkg/service/async.go @@ -16,7 +16,6 @@ import ( "github.com/edgexfoundry/device-sdk-go/internal/cache" "github.com/edgexfoundry/device-sdk-go/internal/common" - "github.com/edgexfoundry/device-sdk-go/internal/handler" "github.com/edgexfoundry/device-sdk-go/internal/transformer" dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models" "github.com/edgexfoundry/go-mod-core-contracts/clients/logger" @@ -122,9 +121,8 @@ func (s *DeviceService) processAsyncFilterAndAdd(ctx context.Context, wg *sync.W case <-ctx.Done(): return case devices := <-s.deviceCh: - id := handler.ReleaseLock() + ctx := context.Background() pws := cache.ProvisionWatchers().All() - ctx := context.WithValue(context.Background(), common.CorrelationHeader, id) for _, d := range devices { for _, pw := range pws { if whitelistPass(d, pw, s.LoggingClient) && blacklistPass(d, pw, s.LoggingClient) {