Partial fix for ONOS-6767.

- pruning removed annotation tombstones
- processing netcfg only on master node
- swapping priority of processing of geo/grid coordinates

Change-Id: Icade1032f94ea774136d863d388402c79094c5a7
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java b/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
index a78987c..2a0eeb5 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
@@ -205,6 +205,16 @@
         throw new IllegalArgumentException("Expecting HashMap instance");
     }
 
+    private static HashMap<String, String> compress(Map<String, String> original) {
+        HashMap<String, String> compressed = new HashMap<>();
+        original.forEach((k, v) -> {
+            if (!Objects.equals(v, Builder.REMOVED)) {
+                compressed.put(k, v);
+            }
+        });
+        return compressed;
+    }
+
     @Override
     public String toString() {
         return (map == null) ? "null" : map.toString();
@@ -289,11 +299,22 @@
 
         /**
          * Returns immutable annotations built from the accrued key/values pairs.
+         * Any removed annotation tombstones will be preserved.
          *
          * @return annotations
          */
         public DefaultAnnotations build() {
             return new DefaultAnnotations(copy(builder));
         }
+
+        /**
+         * Returns immutable annotations built from the accrued key/values
+         * pairs after compressing them to eliminate removed annotation tombstones.
+         *
+         * @return annotations
+         */
+        public DefaultAnnotations buildCompressed() {
+            return new DefaultAnnotations(compress(builder));
+        }
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/BasicElementOperator.java b/core/net/src/main/java/org/onosproject/net/device/impl/BasicElementOperator.java
index 29333e6..a666266 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/BasicElementOperator.java
+++ b/core/net/src/main/java/org/onosproject/net/device/impl/BasicElementOperator.java
@@ -50,16 +50,22 @@
         }
 
         if (Objects.equals(cfg.locType(), BasicElementConfig.LOC_TYPE_NONE)) {
+            // Wipe-out both grid and geo coordinates.
             builder.remove(AnnotationKeys.GRID_X).remove(AnnotationKeys.GRID_Y);
             builder.remove(AnnotationKeys.LATITUDE).remove(AnnotationKeys.LONGITUDE);
-        } else if (cfg.geoCoordsSet()) {
-            builder.set(AnnotationKeys.LATITUDE, Double.toString(cfg.latitude()));
-            builder.set(AnnotationKeys.LONGITUDE, Double.toString(cfg.longitude()));
-            builder.remove(AnnotationKeys.GRID_X).remove(AnnotationKeys.GRID_Y);
+
         } else if (cfg.gridCoordsSet()) {
+            // Give priority to coordinate-based scheme as it requires explicit
+            // location type. Set grid coordinates and wipe-out geo coordinates.
             builder.set(AnnotationKeys.GRID_Y, Double.toString(cfg.gridY()));
             builder.set(AnnotationKeys.GRID_X, Double.toString(cfg.gridX()));
             builder.remove(AnnotationKeys.LATITUDE).remove(AnnotationKeys.LONGITUDE);
+
+        } else if (cfg.geoCoordsSet()) {
+            // Set geo coordinates and wipe-out grid coordinates.
+            builder.set(AnnotationKeys.LATITUDE, Double.toString(cfg.latitude()));
+            builder.set(AnnotationKeys.LONGITUDE, Double.toString(cfg.longitude()));
+            builder.remove(AnnotationKeys.GRID_X).remove(AnnotationKeys.GRID_Y);
         }
 
         if (cfg.rackAddress() != null) {
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
index 1892ae8..caab65b 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
@@ -1023,7 +1023,8 @@
                     && (event.configClass().equals(BasicDeviceConfig.class)
                     || portOpsIndex.containsKey(event.configClass())
                     || event.configClass().equals(PortDescriptionsConfig.class)
-                    || event.configClass().equals(DeviceAnnotationConfig.class));
+                    || event.configClass().equals(DeviceAnnotationConfig.class))
+                    && mastershipService.isLocalMaster((DeviceId) event.subject());
         }
 
         @Override
diff --git a/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java b/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
index de6d2f0..df59f17 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
@@ -362,6 +362,7 @@
                 // outdated event, ignored.
                 return null;
             }
+
             if (oldDevice == null) {
                 // REGISTER
                 if (!deltaDesc.value().isDefaultAvailable()) {
@@ -1165,7 +1166,7 @@
 
         return new DefaultDevice(primary, deviceId, type, manufacturer,
                                  hwVersion, swVersion, serialNumber,
-                                 chassisId, annotations.build());
+                                 chassisId, annotations.buildCompressed());
     }
 
     private Port buildTypedPort(Device device, PortNumber number, boolean isEnabled,