Sho SHIMIZU
Committed by Sho Shimizu

Compaction of discrete resources with range based representation

This resolves ONOS-4281

Change-Id: I0739ba94cc0b3ce617e2db44307fef396dcfb942
(cherry picked from commit 34e2c1c2)
...@@ -23,6 +23,7 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -23,6 +23,7 @@ import org.apache.felix.scr.annotations.Reference;
23 import org.apache.felix.scr.annotations.ReferenceCardinality; 23 import org.apache.felix.scr.annotations.ReferenceCardinality;
24 import org.apache.felix.scr.annotations.Service; 24 import org.apache.felix.scr.annotations.Service;
25 import org.onlab.util.Tools; 25 import org.onlab.util.Tools;
26 +import org.onlab.util.KryoNamespace;
26 import org.onosproject.net.resource.ContinuousResource; 27 import org.onosproject.net.resource.ContinuousResource;
27 import org.onosproject.net.resource.ContinuousResourceId; 28 import org.onosproject.net.resource.ContinuousResourceId;
28 import org.onosproject.net.resource.DiscreteResource; 29 import org.onosproject.net.resource.DiscreteResource;
...@@ -45,7 +46,6 @@ import org.onosproject.store.service.TransactionContext; ...@@ -45,7 +46,6 @@ import org.onosproject.store.service.TransactionContext;
45 import org.slf4j.Logger; 46 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory; 47 import org.slf4j.LoggerFactory;
47 48
48 -import java.util.Arrays;
49 import java.util.Collection; 49 import java.util.Collection;
50 import java.util.LinkedHashMap; 50 import java.util.LinkedHashMap;
51 import java.util.List; 51 import java.util.List;
...@@ -70,11 +70,14 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour ...@@ -70,11 +70,14 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour
70 implements ResourceStore { 70 implements ResourceStore {
71 private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class); 71 private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class);
72 72
73 - static final Serializer SERIALIZER = Serializer.using( 73 + static final Serializer SERIALIZER = Serializer.using(KryoNamespace.newBuilder()
74 - Arrays.asList(KryoNamespaces.API), 74 + .register(KryoNamespaces.API)
75 - UnifiedDiscreteResources.class, 75 + .register(UnifiedDiscreteResources.class)
76 - NonEncodableDiscreteResources.class, 76 + .register(new EncodableDiscreteResourcesSerializer(), EncodableDiscreteResources.class)
77 - ContinuousResourceAllocation.class); 77 + .register(NonEncodableDiscreteResources.class)
78 + .register(EmptyDiscreteResources.class)
79 + .register(ContinuousResourceAllocation.class)
80 + .build());
78 81
79 // TODO: We should provide centralized values for this 82 // TODO: We should provide centralized values for this
80 static final int MAX_RETRIES = 5; 83 static final int MAX_RETRIES = 5;
......
...@@ -32,7 +32,7 @@ interface DiscreteResources { ...@@ -32,7 +32,7 @@ interface DiscreteResources {
32 * @return a empty set. 32 * @return a empty set.
33 */ 33 */
34 static DiscreteResources empty() { 34 static DiscreteResources empty() {
35 - return UnifiedDiscreteResources.empty(); 35 + return EmptyDiscreteResources.INSTANCE;
36 } 36 }
37 37
38 /** 38 /**
...@@ -41,7 +41,7 @@ interface DiscreteResources { ...@@ -41,7 +41,7 @@ interface DiscreteResources {
41 * @param resources resources 41 * @param resources resources
42 * @return instance 42 * @return instance
43 */ 43 */
44 - static DiscreteResources of(List<DiscreteResource> resources) { 44 + static DiscreteResources of(Set<DiscreteResource> resources) {
45 return UnifiedDiscreteResources.of(resources); 45 return UnifiedDiscreteResources.of(resources);
46 } 46 }
47 47
......
...@@ -43,6 +43,10 @@ final class EncodableDiscreteResources implements DiscreteResources { ...@@ -43,6 +43,10 @@ final class EncodableDiscreteResources implements DiscreteResources {
43 } 43 }
44 44
45 static DiscreteResources of(Set<DiscreteResource> resources) { 45 static DiscreteResources of(Set<DiscreteResource> resources) {
46 + if (resources.isEmpty()) {
47 + return DiscreteResources.empty();
48 + }
49 +
46 DiscreteResource parent = resources.iterator().next().parent().get(); 50 DiscreteResource parent = resources.iterator().next().parent().get();
47 return of(parent, resources); 51 return of(parent, resources);
48 } 52 }
......
...@@ -30,26 +30,23 @@ import java.util.Set; ...@@ -30,26 +30,23 @@ import java.util.Set;
30 final class NonEncodableDiscreteResources implements DiscreteResources { 30 final class NonEncodableDiscreteResources implements DiscreteResources {
31 private final Set<DiscreteResource> values; 31 private final Set<DiscreteResource> values;
32 32
33 - static NonEncodableDiscreteResources empty() { 33 + static DiscreteResources of(Set<DiscreteResource> resources) {
34 - return new NonEncodableDiscreteResources(); 34 + if (resources.isEmpty()) {
35 - } 35 + return DiscreteResources.empty();
36 + }
36 37
37 - static NonEncodableDiscreteResources of(List<DiscreteResource> resources) {
38 return new NonEncodableDiscreteResources(resources); 38 return new NonEncodableDiscreteResources(resources);
39 } 39 }
40 40
41 - private NonEncodableDiscreteResources() {
42 - this.values = new LinkedHashSet<>();
43 - }
44 -
45 - private NonEncodableDiscreteResources(List<DiscreteResource> values) {
46 - this.values = new LinkedHashSet<>(values);
47 - }
48 -
49 private NonEncodableDiscreteResources(Set<DiscreteResource> values) { 41 private NonEncodableDiscreteResources(Set<DiscreteResource> values) {
50 this.values = values; 42 this.values = values;
51 } 43 }
52 44
45 + // for serializer
46 + private NonEncodableDiscreteResources() {
47 + this.values = null;
48 + }
49 +
53 @Override 50 @Override
54 public Optional<DiscreteResource> lookup(DiscreteResourceId id) { 51 public Optional<DiscreteResource> lookup(DiscreteResourceId id) {
55 DiscreteResource resource = Resources.discrete(id).resource(); 52 DiscreteResource resource = Resources.discrete(id).resource();
......
...@@ -24,6 +24,7 @@ import org.onosproject.store.service.TransactionalMap; ...@@ -24,6 +24,7 @@ import org.onosproject.store.service.TransactionalMap;
24 import org.slf4j.Logger; 24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory; 25 import org.slf4j.LoggerFactory;
26 26
27 +import java.util.LinkedHashSet;
27 import java.util.List; 28 import java.util.List;
28 import java.util.Optional; 29 import java.util.Optional;
29 30
...@@ -59,7 +60,7 @@ class TransactionalDiscreteResourceSubStore { ...@@ -59,7 +60,7 @@ class TransactionalDiscreteResourceSubStore {
59 return true; 60 return true;
60 } 61 }
61 62
62 - DiscreteResources requested = DiscreteResources.of(values); 63 + DiscreteResources requested = DiscreteResources.of(new LinkedHashSet<>(values));
63 DiscreteResources oldValues = childMap.putIfAbsent(key, requested); 64 DiscreteResources oldValues = childMap.putIfAbsent(key, requested);
64 if (oldValues == null) { 65 if (oldValues == null) {
65 return true; 66 return true;
......
...@@ -15,12 +15,18 @@ ...@@ -15,12 +15,18 @@
15 */ 15 */
16 package org.onosproject.store.resource.impl; 16 package org.onosproject.store.resource.impl;
17 17
18 +import com.google.common.collect.Sets;
18 import org.onosproject.net.resource.DiscreteResource; 19 import org.onosproject.net.resource.DiscreteResource;
19 import org.onosproject.net.resource.DiscreteResourceId; 20 import org.onosproject.net.resource.DiscreteResourceId;
21 +import org.onosproject.net.resource.Resources;
20 22
23 +import java.util.LinkedHashSet;
21 import java.util.List; 24 import java.util.List;
25 +import java.util.Map;
22 import java.util.Optional; 26 import java.util.Optional;
23 import java.util.Set; 27 import java.util.Set;
28 +import java.util.stream.Collectors;
29 +import java.util.stream.Stream;
24 30
25 /** 31 /**
26 * Represents a set of resources containing resources that can be encoded as integer 32 * Represents a set of resources containing resources that can be encoded as integer
...@@ -28,55 +34,66 @@ import java.util.Set; ...@@ -28,55 +34,66 @@ import java.util.Set;
28 */ 34 */
29 final class UnifiedDiscreteResources implements DiscreteResources { 35 final class UnifiedDiscreteResources implements DiscreteResources {
30 private final DiscreteResources nonEncodables; 36 private final DiscreteResources nonEncodables;
37 + private final DiscreteResources encodables;
38 + private static final Codecs CODECS = Codecs.getInstance();
31 39
32 - static DiscreteResources empty() { 40 + static DiscreteResources of(Set<DiscreteResource> resources) {
33 - return new UnifiedDiscreteResources(); 41 + if (resources.isEmpty()) {
34 - } 42 + return DiscreteResources.empty();
35 - 43 + }
36 - static DiscreteResources of(List<DiscreteResource> resources) {
37 - return new UnifiedDiscreteResources(resources);
38 - }
39 44
40 - private UnifiedDiscreteResources() { 45 + Map<Boolean, Set<DiscreteResource>> partitioned = resources.stream()
41 - this.nonEncodables = NonEncodableDiscreteResources.empty(); 46 + .collect(Collectors.partitioningBy(CODECS::isEncodable, Collectors.toCollection(LinkedHashSet::new)));
47 + return new UnifiedDiscreteResources(
48 + NonEncodableDiscreteResources.of(partitioned.get(false)),
49 + EncodableDiscreteResources.of(partitioned.get(true))
50 + );
42 } 51 }
43 52
44 - private UnifiedDiscreteResources(List<DiscreteResource> resources) { 53 + private UnifiedDiscreteResources(DiscreteResources nonEncodables, DiscreteResources encodables) {
45 - this.nonEncodables = NonEncodableDiscreteResources.of(resources); 54 + this.nonEncodables = nonEncodables;
55 + this.encodables = encodables;
46 } 56 }
47 57
48 @Override 58 @Override
49 public Optional<DiscreteResource> lookup(DiscreteResourceId id) { 59 public Optional<DiscreteResource> lookup(DiscreteResourceId id) {
60 + if (CODECS.isEncodable(Resources.discrete(id).resource())) {
61 + return encodables.lookup(id);
62 + }
63 +
50 return nonEncodables.lookup(id); 64 return nonEncodables.lookup(id);
51 } 65 }
52 66
53 @Override 67 @Override
54 public DiscreteResources difference(DiscreteResources other) { 68 public DiscreteResources difference(DiscreteResources other) {
55 - return nonEncodables.difference(other); 69 + return of(Sets.difference(values(), other.values()));
56 } 70 }
57 71
58 @Override 72 @Override
59 public boolean isEmpty() { 73 public boolean isEmpty() {
60 - return nonEncodables.isEmpty(); 74 + return nonEncodables.isEmpty() && encodables.isEmpty();
61 } 75 }
62 76
63 @Override 77 @Override
64 public boolean containsAny(List<DiscreteResource> other) { 78 public boolean containsAny(List<DiscreteResource> other) {
65 - return nonEncodables.containsAny(other); 79 + Map<Boolean, List<DiscreteResource>> partitioned = other.stream()
80 + .collect(Collectors.partitioningBy(CODECS::isEncodable));
81 + return nonEncodables.containsAny(partitioned.get(false)) || encodables.containsAny(partitioned.get(true));
66 } 82 }
67 83
68 @Override 84 @Override
69 public DiscreteResources add(DiscreteResources other) { 85 public DiscreteResources add(DiscreteResources other) {
70 - return nonEncodables.add(other); 86 + return of(Sets.union(this.values(), other.values()));
71 } 87 }
72 88
73 @Override 89 @Override
74 public DiscreteResources remove(List<DiscreteResource> removed) { 90 public DiscreteResources remove(List<DiscreteResource> removed) {
75 - return nonEncodables.remove(removed); 91 + return of(Sets.difference(values(), new LinkedHashSet<>(removed)));
76 } 92 }
77 93
78 @Override 94 @Override
79 public Set<DiscreteResource> values() { 95 public Set<DiscreteResource> values() {
80 - return nonEncodables.values(); 96 + return Stream.concat(encodables.values().stream(), nonEncodables.values().stream())
97 + .collect(Collectors.toCollection(LinkedHashSet::new));
81 } 98 }
82 } 99 }
......