[VOL-1658] Address disable/delete of a device in Pre-prov state

This commit addresses the case where a user wants to disable a
preprovisioned device and also delete it.  It addresses part of the
issue raised by VOL-1658.

Change-Id: Iac8adf45070a234c5505ed800f77150d8ed85156
diff --git a/rw_core/core/device_ownership.go b/rw_core/core/device_ownership.go
index e746444..49d860a 100644
--- a/rw_core/core/device_ownership.go
+++ b/rw_core/core/device_ownership.go
@@ -50,6 +50,7 @@
 	deviceMapLock      *sync.RWMutex
 	deviceToKeyMap     map[string]string
 	deviceToKeyMapLock *sync.RWMutex
+	ownershipLock      *sync.RWMutex
 }
 
 func NewDeviceOwnership(id string, kvClient kvstore.Client, deviceMgr *DeviceManager, logicalDeviceMgr *LogicalDeviceManager, ownershipPrefix string, reservationTimeout int64) *DeviceOwnership {
@@ -65,6 +66,7 @@
 	deviceOwnership.deviceMapLock = &sync.RWMutex{}
 	deviceOwnership.deviceToKeyMap = make(map[string]string)
 	deviceOwnership.deviceToKeyMapLock = &sync.RWMutex{}
+	deviceOwnership.ownershipLock = &sync.RWMutex{}
 	return &deviceOwnership
 }
 
@@ -109,21 +111,23 @@
 }
 
 func (da *DeviceOwnership) MonitorOwnership(id string, chnl chan int) {
+	log.Debugw("start-device-monitoring", log.Fields{"id": id})
 	op := "starting"
 	exit := false
 	ticker := time.NewTicker(time.Duration(da.reservationTimeout) / 3 * time.Second)
 	for {
 		select {
 		case <-da.exitChannel:
-			log.Infow("closing-monitoring", log.Fields{"Id": id})
+			log.Debugw("closing-monitoring", log.Fields{"Id": id})
 			exit = true
 		case <-ticker.C:
 			log.Debugw(fmt.Sprintf("%s-reservation", op), log.Fields{"Id": id})
 		case <-chnl:
-			log.Infow("closing-device-monitoring", log.Fields{"Id": id})
+			log.Debugw("closing-device-monitoring", log.Fields{"Id": id})
 			exit = true
 		}
 		if exit {
+			log.Infow("exiting-device-monitoring", log.Fields{"Id": id})
 			ticker.Stop()
 			break
 		}
@@ -144,6 +148,7 @@
 			}
 		}
 	}
+	log.Debugw("device-monitoring-stopped", log.Fields{"id": id})
 }
 
 func (da *DeviceOwnership) getOwnership(id string) (bool, bool) {
@@ -188,6 +193,12 @@
 		da.deviceToKeyMapLock.Unlock()
 	}
 
+	// Add a lock to prevent creation of two separate monitoring routines for the same device. When a NB request for a
+	// device not in memory is received this results in this function being called in rapid succession, once when
+	// loading the device and once when handling the NB request.
+	da.ownershipLock.Lock()
+	defer da.ownershipLock.Unlock()
+
 	deviceOwned, ownedByMe := da.getOwnership(ownershipKey)
 	if deviceOwned {
 		log.Debugw("ownership", log.Fields{"Id": ownershipKey, "owned": ownedByMe})