alshabib
Committed by Gerrit Code Review

Adding tests for meter service.

Change-Id: Ic220fdaa89b421661019f1a6ef23c7b02eef127c
...@@ -22,10 +22,9 @@ import org.onosproject.core.CoreService; ...@@ -22,10 +22,9 @@ import org.onosproject.core.CoreService;
22 import org.onosproject.net.DeviceId; 22 import org.onosproject.net.DeviceId;
23 import org.onosproject.net.meter.Band; 23 import org.onosproject.net.meter.Band;
24 import org.onosproject.net.meter.DefaultBand; 24 import org.onosproject.net.meter.DefaultBand;
25 -import org.onosproject.net.meter.DefaultMeter; 25 +import org.onosproject.net.meter.DefaultMeterRequest;
26 import org.onosproject.net.meter.Meter; 26 import org.onosproject.net.meter.Meter;
27 -import org.onosproject.net.meter.MeterId; 27 +import org.onosproject.net.meter.MeterRequest;
28 -import org.onosproject.net.meter.MeterOperation;
29 import org.onosproject.net.meter.MeterService; 28 import org.onosproject.net.meter.MeterService;
30 29
31 import java.util.Collections; 30 import java.util.Collections;
...@@ -41,7 +40,7 @@ public class AddMeter extends AbstractShellCommand { ...@@ -41,7 +40,7 @@ public class AddMeter extends AbstractShellCommand {
41 required = true, multiValued = false) 40 required = true, multiValued = false)
42 String uri = null; 41 String uri = null;
43 42
44 - private final String appId = "org.onosproject.cli.addMeter"; 43 + private final String appId = "org.onosproject.cli.meterCmd";
45 44
46 @Override 45 @Override
47 protected void execute() { 46 protected void execute() {
...@@ -50,25 +49,20 @@ public class AddMeter extends AbstractShellCommand { ...@@ -50,25 +49,20 @@ public class AddMeter extends AbstractShellCommand {
50 49
51 DeviceId deviceId = DeviceId.deviceId(uri); 50 DeviceId deviceId = DeviceId.deviceId(uri);
52 51
53 - MeterId meterId = service.allocateMeterId();
54 -
55 Band band = DefaultBand.builder() 52 Band band = DefaultBand.builder()
56 .ofType(Band.Type.DROP) 53 .ofType(Band.Type.DROP)
57 .withRate(500) 54 .withRate(500)
58 .build(); 55 .build();
59 56
60 57
61 - Meter meter = DefaultMeter.builder() 58 + MeterRequest request = DefaultMeterRequest.builder()
62 .forDevice(deviceId) 59 .forDevice(deviceId)
63 .fromApp(coreService.registerApplication(appId)) 60 .fromApp(coreService.registerApplication(appId))
64 - .withId(meterId)
65 .withUnit(Meter.Unit.KB_PER_SEC) 61 .withUnit(Meter.Unit.KB_PER_SEC)
66 .withBands(Collections.singleton(band)) 62 .withBands(Collections.singleton(band))
67 - .build(); 63 + .add();
68 -
69 - MeterOperation op = new MeterOperation(meter, MeterOperation.Type.ADD, null);
70 64
71 - service.addMeter(op); 65 + service.submit(request);
72 66
73 } 67 }
74 } 68 }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.meter; 16 package org.onosproject.net.meter;
17 17
18 +import com.google.common.base.Objects;
18 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
19 import org.onosproject.core.ApplicationId; 20 import org.onosproject.core.ApplicationId;
20 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
...@@ -151,6 +152,26 @@ public final class DefaultMeter implements Meter, MeterEntry { ...@@ -151,6 +152,26 @@ public final class DefaultMeter implements Meter, MeterEntry {
151 .add("bands", bands).toString(); 152 .add("bands", bands).toString();
152 } 153 }
153 154
155 + @Override
156 + public boolean equals(Object o) {
157 + if (this == o) {
158 + return true;
159 + }
160 + if (o == null || getClass() != o.getClass()) {
161 + return false;
162 + }
163 + DefaultMeter that = (DefaultMeter) o;
164 + return Objects.equal(id, that.id) &&
165 + Objects.equal(appId, that.appId) &&
166 + Objects.equal(unit, that.unit) &&
167 + Objects.equal(deviceId, that.deviceId);
168 + }
169 +
170 + @Override
171 + public int hashCode() {
172 + return Objects.hashCode(id, appId, unit, deviceId);
173 + }
174 +
154 public static final class Builder implements Meter.Builder { 175 public static final class Builder implements Meter.Builder {
155 176
156 private MeterId id; 177 private MeterId id;
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.meter;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import org.onosproject.core.ApplicationId;
20 +import org.onosproject.net.DeviceId;
21 +
22 +import java.util.Collection;
23 +import java.util.Optional;
24 +
25 +import static com.google.common.base.MoreObjects.toStringHelper;
26 +import static com.google.common.base.Preconditions.checkArgument;
27 +import static com.google.common.base.Preconditions.checkNotNull;
28 +
29 +/**
30 + * A default implementation of a meter.
31 + */
32 +public final class DefaultMeterRequest implements MeterRequest {
33 +
34 +
35 +
36 + private final ApplicationId appId;
37 + private final Meter.Unit unit;
38 + private final boolean burst;
39 + private final Collection<Band> bands;
40 + private final DeviceId deviceId;
41 + private final Optional<MeterContext> context;
42 + private final Type op;
43 +
44 + private DefaultMeterRequest(DeviceId deviceId, ApplicationId appId,
45 + Meter.Unit unit, boolean burst,
46 + Collection<Band> bands, MeterContext context, Type op) {
47 + this.deviceId = deviceId;
48 + this.appId = appId;
49 + this.unit = unit;
50 + this.burst = burst;
51 + this.bands = bands;
52 + this.context = Optional.ofNullable(context);
53 + this.op = op;
54 + }
55 +
56 + @Override
57 + public DeviceId deviceId() {
58 + return deviceId;
59 + }
60 +
61 + @Override
62 + public ApplicationId appId() {
63 + return appId;
64 + }
65 +
66 + @Override
67 + public Meter.Unit unit() {
68 + return unit;
69 + }
70 +
71 + @Override
72 + public boolean isBurst() {
73 + return burst;
74 + }
75 +
76 + @Override
77 + public Collection<Band> bands() {
78 + return bands;
79 + }
80 +
81 + @Override
82 + public Optional<MeterContext> context() {
83 + return context;
84 + }
85 +
86 +
87 +
88 + public static Builder builder() {
89 + return new Builder();
90 + }
91 +
92 + @Override
93 + public String toString() {
94 + return toStringHelper(this)
95 + .add("device", deviceId)
96 + .add("appId", appId.name())
97 + .add("unit", unit)
98 + .add("isBurst", burst)
99 + .add("bands", bands).toString();
100 + }
101 +
102 + public static final class Builder implements MeterRequest.Builder {
103 +
104 + private ApplicationId appId;
105 + private Meter.Unit unit = Meter.Unit.KB_PER_SEC;
106 + private boolean burst = false;
107 + private Collection<Band> bands;
108 + private DeviceId deviceId;
109 + private MeterContext context;
110 +
111 +
112 + @Override
113 + public MeterRequest.Builder forDevice(DeviceId deviceId) {
114 + this.deviceId = deviceId;
115 + return this;
116 + }
117 +
118 + @Override
119 + public MeterRequest.Builder fromApp(ApplicationId appId) {
120 + this.appId = appId;
121 + return this;
122 + }
123 +
124 + @Override
125 + public MeterRequest.Builder withUnit(Meter.Unit unit) {
126 + this.unit = unit;
127 + return this;
128 + }
129 +
130 + @Override
131 + public MeterRequest.Builder burst() {
132 + this.burst = true;
133 + return this;
134 + }
135 +
136 + @Override
137 + public MeterRequest.Builder withBands(Collection<Band> bands) {
138 + this.bands = ImmutableSet.copyOf(bands);
139 + return this;
140 + }
141 +
142 + @Override
143 + public MeterRequest.Builder withContext(MeterContext context) {
144 + this.context = context;
145 + return this;
146 + }
147 +
148 + @Override
149 + public MeterRequest add() {
150 + validate();
151 + return new DefaultMeterRequest(deviceId, appId, unit, burst, bands,
152 + context, Type.ADD);
153 + }
154 +
155 + @Override
156 + public MeterRequest remove() {
157 + validate();
158 + return new DefaultMeterRequest(deviceId, appId, unit, burst, bands,
159 + context, Type.REMOVE);
160 + }
161 +
162 + private void validate() {
163 + checkNotNull(deviceId, "Must specify a device");
164 + checkNotNull(bands, "Must have bands.");
165 + checkArgument(bands.size() > 0, "Must have at least one band.");
166 + checkNotNull(appId, "Must have an application id");
167 + }
168 +
169 +
170 + }
171 +}
...@@ -130,7 +130,7 @@ public interface Meter { ...@@ -130,7 +130,7 @@ public interface Meter {
130 /** 130 /**
131 * Assigns the id to this meter. 131 * Assigns the id to this meter.
132 * 132 *
133 - * @param id a meter id 133 + * @param id a e
134 * @return this 134 * @return this
135 */ 135 */
136 Builder withId(MeterId id); 136 Builder withId(MeterId id);
......
...@@ -26,7 +26,7 @@ public interface MeterContext { ...@@ -26,7 +26,7 @@ public interface MeterContext {
26 * 26 *
27 * @param op a meter 27 * @param op a meter
28 */ 28 */
29 - default void onSuccess(Meter op) {} 29 + default void onSuccess(MeterRequest op) {}
30 30
31 /** 31 /**
32 * Invoked when error is encountered while installing a meter. 32 * Invoked when error is encountered while installing a meter.
...@@ -34,5 +34,5 @@ public interface MeterContext { ...@@ -34,5 +34,5 @@ public interface MeterContext {
34 * @param op a meter 34 * @param op a meter
35 * @param reason the reason why it failed 35 * @param reason the reason why it failed
36 */ 36 */
37 - default void onError(Meter op, MeterFailReason reason) {} 37 + default void onError(MeterRequest op, MeterFailReason reason) {}
38 } 38 }
......
...@@ -16,15 +16,13 @@ ...@@ -16,15 +16,13 @@
16 package org.onosproject.net.meter; 16 package org.onosproject.net.meter;
17 17
18 import com.google.common.base.MoreObjects; 18 import com.google.common.base.MoreObjects;
19 - 19 +import com.google.common.base.Objects;
20 -import java.util.Optional;
21 20
22 /** 21 /**
23 * Representation of an operation on the meter table. 22 * Representation of an operation on the meter table.
24 */ 23 */
25 public class MeterOperation { 24 public class MeterOperation {
26 25
27 - private final Optional<MeterContext> context;
28 26
29 /** 27 /**
30 * Tyoe of meter operation. 28 * Tyoe of meter operation.
...@@ -39,10 +37,9 @@ public class MeterOperation { ...@@ -39,10 +37,9 @@ public class MeterOperation {
39 private final Type type; 37 private final Type type;
40 38
41 39
42 - public MeterOperation(Meter meter, Type type, MeterContext context) { 40 + public MeterOperation(Meter meter, Type type) {
43 this.meter = meter; 41 this.meter = meter;
44 this.type = type; 42 this.type = type;
45 - this.context = Optional.ofNullable(context);
46 } 43 }
47 44
48 /** 45 /**
...@@ -63,16 +60,6 @@ public class MeterOperation { ...@@ -63,16 +60,6 @@ public class MeterOperation {
63 return meter; 60 return meter;
64 } 61 }
65 62
66 - /**
67 - * Returns a context which allows application to
68 - * be notified on the success value of this operation.
69 - *
70 - * @return a meter context
71 - */
72 - public Optional<MeterContext> context() {
73 - return this.context;
74 - }
75 -
76 @Override 63 @Override
77 public String toString() { 64 public String toString() {
78 return MoreObjects.toStringHelper(this) 65 return MoreObjects.toStringHelper(this)
...@@ -80,4 +67,22 @@ public class MeterOperation { ...@@ -80,4 +67,22 @@ public class MeterOperation {
80 .add("type", type) 67 .add("type", type)
81 .toString(); 68 .toString();
82 } 69 }
70 +
71 + @Override
72 + public boolean equals(Object o) {
73 + if (this == o) {
74 + return true;
75 + }
76 + if (o == null || getClass() != o.getClass()) {
77 + return false;
78 + }
79 + MeterOperation that = (MeterOperation) o;
80 + return Objects.equal(meter, that.meter) &&
81 + Objects.equal(type, that.type);
82 + }
83 +
84 + @Override
85 + public int hashCode() {
86 + return Objects.hashCode(meter, type);
87 + }
83 } 88 }
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.meter;
17 +
18 +import org.onosproject.core.ApplicationId;
19 +import org.onosproject.net.DeviceId;
20 +
21 +import java.util.Collection;
22 +import java.util.Optional;
23 +
24 +/**
25 + * Represents a generalized meter request to be deployed on a device.
26 + */
27 +public interface MeterRequest {
28 +
29 + enum Type {
30 + ADD,
31 + MODIFY,
32 + REMOVE
33 + }
34 +
35 + /**
36 + * The target device for this meter.
37 + *
38 + * @return a device id
39 + */
40 + DeviceId deviceId();
41 +
42 + /**
43 + * The id of the application which created this meter.
44 + *
45 + * @return an application id
46 + */
47 + ApplicationId appId();
48 +
49 + /**
50 + * The unit used within this meter.
51 + *
52 + * @return the unit
53 + */
54 + Meter.Unit unit();
55 +
56 + /**
57 + * Signals whether this meter applies to bursts only.
58 + *
59 + * @return a boolean
60 + */
61 + boolean isBurst();
62 +
63 + /**
64 + * The collection of bands to apply on the dataplane.
65 + *
66 + * @return a collection of bands.
67 + */
68 + Collection<Band> bands();
69 +
70 + /**
71 + * Returns the callback context for this meter.
72 + *
73 + * @return an optional meter context
74 + */
75 + Optional<MeterContext> context();
76 +
77 + /**
78 + * A meter builder.
79 + */
80 + interface Builder {
81 +
82 + /**
83 + * Assigns the target device for this meter.
84 + *
85 + * @param deviceId a device id
86 + * @return this
87 + */
88 + Builder forDevice(DeviceId deviceId);
89 +
90 + /**
91 + * Assigns the application that built this meter.
92 + *
93 + * @param appId an application id
94 + * @return this
95 + */
96 + Builder fromApp(ApplicationId appId);
97 +
98 + /**
99 + * Assigns the @See Unit to use for this meter.
100 + * Defaults to kb/s
101 + *
102 + * @param unit a unit
103 + * @return this
104 + */
105 + Builder withUnit(Meter.Unit unit);
106 +
107 + /**
108 + * Sets this meter as applicable to burst traffic only.
109 + * Defaults to false.
110 + *
111 + * @return this
112 + */
113 + Builder burst();
114 +
115 + /**
116 + * Assigns bands to this meter. There must be at least one band.
117 + *
118 + * @param bands a collection of bands
119 + * @return this
120 + */
121 + Builder withBands(Collection<Band> bands);
122 +
123 + /**
124 + * Assigns an execution context for this meter request.
125 + *
126 + * @param context a meter context
127 + * @return this
128 + */
129 + Builder withContext(MeterContext context);
130 +
131 + /**
132 + * Requests the addition of a meter.
133 + *
134 + * @return a meter request
135 + */
136 + MeterRequest add();
137 +
138 + /**
139 + * Requests the removal of a meter.
140 + *
141 + * @return a meter request
142 + */
143 + MeterRequest remove();
144 +
145 + }
146 +
147 +}
...@@ -30,23 +30,18 @@ public interface MeterService ...@@ -30,23 +30,18 @@ public interface MeterService
30 /** 30 /**
31 * Adds a meter to the system and performs it installation. 31 * Adds a meter to the system and performs it installation.
32 * 32 *
33 - * @param meter a meter. 33 + * @param meter a meter
34 + * @return a meter (with a meter id)
34 */ 35 */
35 - void addMeter(MeterOperation meter); 36 + Meter submit(MeterRequest meter);
36 -
37 - /**
38 - * Updates a meter by adding statistic information to the meter.
39 - *
40 - * @param meter an updated meter
41 - */
42 - void updateMeter(MeterOperation meter);
43 37
44 /** 38 /**
45 * Remove a meter from the system and the dataplane. 39 * Remove a meter from the system and the dataplane.
46 * 40 *
47 * @param meter a meter to remove 41 * @param meter a meter to remove
42 + * @param meterId the meter id of the meter to remove.
48 */ 43 */
49 - void removeMeter(MeterOperation meter); 44 + void withdraw(MeterRequest meter, MeterId meterId);
50 45
51 /** 46 /**
52 * Fetch the meter by the meter id. 47 * Fetch the meter by the meter id.
...@@ -63,10 +58,4 @@ public interface MeterService ...@@ -63,10 +58,4 @@ public interface MeterService
63 */ 58 */
64 Collection<Meter> getAllMeters(); 59 Collection<Meter> getAllMeters();
65 60
66 - /**
67 - * Allocate a meter id which must be used to create the meter.
68 - *
69 - * @return a meter id
70 - */
71 - MeterId allocateMeterId();
72 } 61 }
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.meter;
17 +
18 +import com.google.common.testing.EqualsTester;
19 +import org.junit.Before;
20 +import org.junit.Test;
21 +
22 +import java.util.Collections;
23 +
24 +import static org.hamcrest.MatcherAssert.assertThat;
25 +import static org.hamcrest.Matchers.is;
26 +import static org.onosproject.net.NetTestTools.APP_ID;
27 +import static org.onosproject.net.NetTestTools.did;
28 +
29 +
30 +/**
31 + * DefaultMeter Tests.
32 + */
33 +public class DefaultMeterTest {
34 +
35 + private Meter m1;
36 + private Meter sameAsm1;
37 + private Meter m2;
38 +
39 + @Before
40 + public void setup() {
41 +
42 + Band band = DefaultBand.builder()
43 + .ofType(Band.Type.DROP)
44 + .withRate(500)
45 + .build();
46 +
47 + m1 = DefaultMeter.builder()
48 + .forDevice(did("1"))
49 + .fromApp(APP_ID)
50 + .withId(MeterId.meterId(1))
51 + .withUnit(Meter.Unit.KB_PER_SEC)
52 + .withBands(Collections.singletonList(band))
53 + .build();
54 +
55 + sameAsm1 = DefaultMeter.builder()
56 + .forDevice(did("1"))
57 + .fromApp(APP_ID)
58 + .withId(MeterId.meterId(1))
59 + .withUnit(Meter.Unit.KB_PER_SEC)
60 + .withBands(Collections.singletonList(band))
61 + .build();
62 +
63 + m2 = DefaultMeter.builder()
64 + .forDevice(did("2"))
65 + .fromApp(APP_ID)
66 + .withId(MeterId.meterId(2))
67 + .withUnit(Meter.Unit.KB_PER_SEC)
68 + .withBands(Collections.singletonList(band))
69 + .build();
70 +
71 + }
72 +
73 + @Test
74 + public void testEquality() {
75 + new EqualsTester()
76 + .addEqualityGroup(m1, sameAsm1)
77 + .addEqualityGroup(m2).testEquals();
78 + }
79 +
80 + @Test
81 + public void testConstruction() {
82 + DefaultMeter m = (DefaultMeter) m1;
83 +
84 + assertThat(m.deviceId(), is(did("1")));
85 + assertThat(m.appId(), is(APP_ID));
86 + assertThat(m.id(), is(MeterId.meterId(1)));
87 + assertThat(m.isBurst(), is(false));
88 +
89 + assertThat(m.life(), is(0L));
90 + assertThat(m.bytesSeen(), is(0L));
91 + assertThat(m.packetsSeen(), is(0L));
92 + assertThat(m.referenceCount(), is(0L));
93 +
94 + }
95 +
96 +
97 +
98 +
99 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net.meter;
17 +
18 +import com.google.common.testing.EqualsTester;
19 +import org.junit.Test;
20 +import org.onosproject.core.ApplicationId;
21 +import org.onosproject.net.DeviceId;
22 +
23 +import java.util.Collection;
24 +
25 +import static org.hamcrest.MatcherAssert.assertThat;
26 +import static org.hamcrest.Matchers.is;
27 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBaseClass;
28 +
29 +/**
30 + * Unit tests for the MeterOperationTest object.
31 + */
32 +public class MeterOperationTest {
33 +
34 +
35 +
36 + /**
37 + * Checks that the MeterOperation class is immutable.
38 + */
39 + @Test
40 + public void testImmutability() {
41 + assertThatClassIsImmutableBaseClass(MeterOperation.class);
42 + }
43 +
44 + @Test
45 + public void testEquality() {
46 + final Meter m1 = new TestMeter();
47 + final Meter m2 = new TestMeter();
48 + final MeterOperation op1 = new MeterOperation(m1,
49 + MeterOperation.Type.ADD);
50 + final MeterOperation sameAsOp1 = new MeterOperation(m1,
51 + MeterOperation.Type.ADD);
52 + final MeterOperation op2 = new MeterOperation(m2,
53 + MeterOperation.Type.ADD);
54 +
55 + new EqualsTester()
56 + .addEqualityGroup(op1, sameAsOp1)
57 + .addEqualityGroup(op2)
58 + .testEquals();
59 + }
60 +
61 + @Test
62 + public void testConstruction() {
63 + final Meter m1 = new TestMeter();
64 +
65 + final MeterOperation op = new MeterOperation(m1, MeterOperation.Type.ADD);
66 +
67 + assertThat(op.meter(), is(m1));
68 + }
69 +
70 + private static final class TestMeter implements Meter {
71 +
72 + @Override
73 + public DeviceId deviceId() {
74 + return null;
75 + }
76 +
77 + @Override
78 + public MeterId id() {
79 + return null;
80 + }
81 +
82 + @Override
83 + public ApplicationId appId() {
84 + return null;
85 + }
86 +
87 + @Override
88 + public Unit unit() {
89 + return null;
90 + }
91 +
92 + @Override
93 + public boolean isBurst() {
94 + return false;
95 + }
96 +
97 + @Override
98 + public Collection<Band> bands() {
99 + return null;
100 + }
101 +
102 + @Override
103 + public MeterState state() {
104 + return null;
105 + }
106 +
107 + @Override
108 + public long life() {
109 + return 0;
110 + }
111 +
112 + @Override
113 + public long referenceCount() {
114 + return 0;
115 + }
116 +
117 + @Override
118 + public long packetsSeen() {
119 + return 0;
120 + }
121 +
122 + @Override
123 + public long bytesSeen() {
124 + return 0;
125 + }
126 + }
127 +
128 +}
...@@ -21,6 +21,7 @@ import java.util.LinkedList; ...@@ -21,6 +21,7 @@ import java.util.LinkedList;
21 import java.util.List; 21 import java.util.List;
22 import java.util.Map; 22 import java.util.Map;
23 import java.util.Set; 23 import java.util.Set;
24 +import java.util.concurrent.atomic.AtomicLong;
24 import java.util.function.BiFunction; 25 import java.util.function.BiFunction;
25 import java.util.function.Function; 26 import java.util.function.Function;
26 import java.util.function.Predicate; 27 import java.util.function.Predicate;
...@@ -38,6 +39,7 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> { ...@@ -38,6 +39,7 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
38 private final List<MapEventListener<K, V>> listeners; 39 private final List<MapEventListener<K, V>> listeners;
39 private final HashMap<K, V> map; 40 private final HashMap<K, V> map;
40 private final String mapName; 41 private final String mapName;
42 + private final AtomicLong counter = new AtomicLong(0);
41 43
42 private TestConsistentMap(String mapName) { 44 private TestConsistentMap(String mapName) {
43 map = new HashMap<>(); 45 map = new HashMap<>();
...@@ -46,7 +48,7 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> { ...@@ -46,7 +48,7 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
46 } 48 }
47 49
48 private Versioned<V> version(V v) { 50 private Versioned<V> version(V v) {
49 - return new Versioned<>(v, 1, System.currentTimeMillis()); 51 + return new Versioned<>(v, counter.incrementAndGet(), System.currentTimeMillis());
50 } 52 }
51 53
52 /** 54 /**
...@@ -115,8 +117,12 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> { ...@@ -115,8 +117,12 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
115 117
116 @Override 118 @Override
117 public Versioned<V> put(K key, V value) { 119 public Versioned<V> put(K key, V value) {
118 - Versioned<V> result = version(map.put(key, value)); 120 + Versioned<V> result = version(value);
119 - notifyListeners(mapName, INSERT, key, result); 121 + if (map.put(key, value) == null) {
122 + notifyListeners(mapName, INSERT, key, result);
123 + } else {
124 + notifyListeners(mapName, UPDATE, key, result);
125 + }
120 return result; 126 return result;
121 } 127 }
122 128
...@@ -213,6 +219,11 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> { ...@@ -213,6 +219,11 @@ public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
213 listeners.remove(listener); 219 listeners.remove(listener);
214 } 220 }
215 221
222 + @Override
223 + public Map<K, V> asJavaMap() {
224 + return map;
225 + }
226 +
216 public static Builder builder() { 227 public static Builder builder() {
217 return new Builder(); 228 return new Builder();
218 } 229 }
......
...@@ -32,6 +32,7 @@ import org.onosproject.net.meter.MeterOperation; ...@@ -32,6 +32,7 @@ import org.onosproject.net.meter.MeterOperation;
32 import org.onosproject.net.meter.MeterProvider; 32 import org.onosproject.net.meter.MeterProvider;
33 import org.onosproject.net.meter.MeterProviderRegistry; 33 import org.onosproject.net.meter.MeterProviderRegistry;
34 import org.onosproject.net.meter.MeterProviderService; 34 import org.onosproject.net.meter.MeterProviderService;
35 +import org.onosproject.net.meter.MeterRequest;
35 import org.onosproject.net.meter.MeterService; 36 import org.onosproject.net.meter.MeterService;
36 import org.onosproject.net.meter.MeterState; 37 import org.onosproject.net.meter.MeterState;
37 import org.onosproject.net.meter.MeterStore; 38 import org.onosproject.net.meter.MeterStore;
...@@ -72,7 +73,7 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M ...@@ -72,7 +73,7 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
72 73
73 private AtomicCounter meterIdCounter; 74 private AtomicCounter meterIdCounter;
74 75
75 - private TriConsumer<MeterOperation, MeterStoreResult, Throwable> onComplete; 76 + private TriConsumer<MeterRequest, MeterStoreResult, Throwable> onComplete;
76 77
77 @Activate 78 @Activate
78 public void activate() { 79 public void activate() {
...@@ -82,16 +83,16 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M ...@@ -82,16 +83,16 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
82 83
83 store.setDelegate(delegate); 84 store.setDelegate(delegate);
84 85
85 - onComplete = (op, result, error) -> 86 + onComplete = (request, result, error) ->
86 { 87 {
87 - op.context().ifPresent(c -> { 88 + request.context().ifPresent(c -> {
88 if (error != null) { 89 if (error != null) {
89 - c.onError(op.meter(), MeterFailReason.UNKNOWN); 90 + c.onError(request, MeterFailReason.UNKNOWN);
90 } else { 91 } else {
91 if (result.reason().isPresent()) { 92 if (result.reason().isPresent()) {
92 - c.onError(op.meter(), result.reason().get()); 93 + c.onError(request, result.reason().get());
93 } else { 94 } else {
94 - c.onSuccess(op.meter()); 95 + c.onSuccess(request);
95 } 96 }
96 } 97 }
97 }); 98 });
...@@ -112,27 +113,42 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M ...@@ -112,27 +113,42 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
112 } 113 }
113 114
114 @Override 115 @Override
115 - public void addMeter(MeterOperation op) { 116 + public Meter submit(MeterRequest request) {
116 - DefaultMeter m = (DefaultMeter) op.meter(); 117 +
118 + Meter.Builder mBuilder = DefaultMeter.builder()
119 + .forDevice(request.deviceId())
120 + .fromApp(request.appId())
121 + .withBands(request.bands())
122 + .withId(allocateMeterId())
123 + .withUnit(request.unit());
124 +
125 + if (request.isBurst()) {
126 + mBuilder.burst();
127 + }
128 + DefaultMeter m = (DefaultMeter) mBuilder.build();
117 m.setState(MeterState.PENDING_ADD); 129 m.setState(MeterState.PENDING_ADD);
118 store.storeMeter(m).whenComplete((result, error) -> 130 store.storeMeter(m).whenComplete((result, error) ->
119 - onComplete.accept(op, result, error)); 131 + onComplete.accept(request, result, error));
132 + return m;
120 } 133 }
121 134
122 @Override 135 @Override
123 - public void updateMeter(MeterOperation op) { 136 + public void withdraw(MeterRequest request, MeterId meterId) {
124 - DefaultMeter m = (DefaultMeter) op.meter(); 137 + Meter.Builder mBuilder = DefaultMeter.builder()
125 - m.setState(MeterState.PENDING_ADD); 138 + .forDevice(request.deviceId())
126 - store.updateMeter(m).whenComplete((result, error) -> 139 + .fromApp(request.appId())
127 - onComplete.accept(op, result, error)); 140 + .withBands(request.bands())
128 - } 141 + .withId(meterId)
142 + .withUnit(request.unit());
143 +
144 + if (request.isBurst()) {
145 + mBuilder.burst();
146 + }
129 147
130 - @Override 148 + DefaultMeter m = (DefaultMeter) mBuilder.build();
131 - public void removeMeter(MeterOperation op) {
132 - DefaultMeter m = (DefaultMeter) op.meter();
133 m.setState(MeterState.PENDING_REMOVE); 149 m.setState(MeterState.PENDING_REMOVE);
134 store.deleteMeter(m).whenComplete((result, error) -> 150 store.deleteMeter(m).whenComplete((result, error) ->
135 - onComplete.accept(op, result, error)); 151 + onComplete.accept(request, result, error));
136 } 152 }
137 153
138 @Override 154 @Override
...@@ -145,10 +161,9 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M ...@@ -145,10 +161,9 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
145 return store.getAllMeters(); 161 return store.getAllMeters();
146 } 162 }
147 163
148 - @Override 164 + private MeterId allocateMeterId() {
149 - public MeterId allocateMeterId() {
150 // FIXME: This will break one day. 165 // FIXME: This will break one day.
151 - return MeterId.meterId((int) meterIdCounter.getAndIncrement()); 166 + return MeterId.meterId((int) meterIdCounter.incrementAndGet());
152 } 167 }
153 168
154 private class InternalMeterProviderService 169 private class InternalMeterProviderService
...@@ -185,8 +200,7 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M ...@@ -185,8 +200,7 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
185 if (m.state() == MeterState.PENDING_ADD) { 200 if (m.state() == MeterState.PENDING_ADD) {
186 provider().performMeterOperation(m.deviceId(), 201 provider().performMeterOperation(m.deviceId(),
187 new MeterOperation(m, 202 new MeterOperation(m,
188 - MeterOperation.Type.ADD, 203 + MeterOperation.Type.ADD));
189 - null));
190 } else { 204 } else {
191 store.deleteMeterNow(m); 205 store.deleteMeterNow(m);
192 } 206 }
...@@ -203,13 +217,11 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M ...@@ -203,13 +217,11 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
203 switch (event.type()) { 217 switch (event.type()) {
204 case METER_ADD_REQ: 218 case METER_ADD_REQ:
205 p.performMeterOperation(deviceId, new MeterOperation(event.subject(), 219 p.performMeterOperation(deviceId, new MeterOperation(event.subject(),
206 - MeterOperation.Type.ADD, 220 + MeterOperation.Type.ADD));
207 - null));
208 break; 221 break;
209 case METER_REM_REQ: 222 case METER_REM_REQ:
210 p.performMeterOperation(deviceId, new MeterOperation(event.subject(), 223 p.performMeterOperation(deviceId, new MeterOperation(event.subject(),
211 - MeterOperation.Type.REMOVE, 224 + MeterOperation.Type.REMOVE));
212 - null));
213 break; 225 break;
214 default: 226 default:
215 log.warn("Unknown meter event {}", event.type()); 227 log.warn("Unknown meter event {}", event.type());
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.net.meter.impl;
17 +
18 +import com.google.common.collect.Maps;
19 +import com.google.common.collect.Sets;
20 +import org.junit.After;
21 +import org.junit.Before;
22 +import org.junit.Test;
23 +import org.onlab.junit.TestUtils;
24 +import org.onlab.packet.IpAddress;
25 +import org.onosproject.cluster.ClusterServiceAdapter;
26 +import org.onosproject.cluster.ControllerNode;
27 +import org.onosproject.cluster.DefaultControllerNode;
28 +import org.onosproject.cluster.NodeId;
29 +import org.onosproject.common.event.impl.TestEventDispatcher;
30 +import org.onosproject.core.ApplicationId;
31 +import org.onosproject.core.DefaultApplicationId;
32 +import org.onosproject.incubator.store.meter.impl.DistributedMeterStore;
33 +import org.onosproject.mastership.MastershipServiceAdapter;
34 +import org.onosproject.net.DeviceId;
35 +import org.onosproject.net.meter.Band;
36 +import org.onosproject.net.meter.DefaultBand;
37 +import org.onosproject.net.meter.DefaultMeter;
38 +import org.onosproject.net.meter.DefaultMeterRequest;
39 +import org.onosproject.net.meter.Meter;
40 +import org.onosproject.net.meter.MeterId;
41 +import org.onosproject.net.meter.MeterOperation;
42 +import org.onosproject.net.meter.MeterOperations;
43 +import org.onosproject.net.meter.MeterProvider;
44 +import org.onosproject.net.meter.MeterProviderRegistry;
45 +import org.onosproject.net.meter.MeterProviderService;
46 +import org.onosproject.net.meter.MeterRequest;
47 +import org.onosproject.net.meter.MeterService;
48 +import org.onosproject.net.meter.MeterState;
49 +import org.onosproject.net.provider.AbstractProvider;
50 +import org.onosproject.net.provider.ProviderId;
51 +import org.onosproject.store.service.TestStorageService;
52 +
53 +import java.util.Collections;
54 +import java.util.Map;
55 +import java.util.Set;
56 +
57 +import static org.hamcrest.Matchers.is;
58 +import static org.junit.Assert.assertFalse;
59 +import static org.junit.Assert.assertThat;
60 +import static org.junit.Assert.assertTrue;
61 +import static org.onosproject.net.NetTestTools.APP_ID;
62 +import static org.onosproject.net.NetTestTools.did;
63 +import static org.onosproject.net.NetTestTools.injectEventDispatcher;
64 +
65 +/**
66 + * Meter manager tests.
67 + */
68 +public class MeterManagerTest {
69 +
70 + private static final ProviderId PID = new ProviderId("of", "foo");
71 + private static final NodeId NID_LOCAL = new NodeId("local");
72 + private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
73 +
74 + private MeterService service;
75 + private MeterManager manager;
76 + private DistributedMeterStore meterStore;
77 + private MeterProviderRegistry registry;
78 + private MeterProviderService providerService;
79 +
80 + private TestProvider provider;
81 +
82 + private ApplicationId appId;
83 +
84 +
85 + private Meter m1;
86 + private Meter m2;
87 + private MeterRequest.Builder m1Request;
88 + private MeterRequest.Builder m2Request;
89 +
90 + private Map<MeterId, Meter> meters = Maps.newHashMap();
91 +
92 + @Before
93 + public void setup() throws Exception {
94 + meterStore = new DistributedMeterStore();
95 + TestUtils.setField(meterStore, "storageService", new TestStorageService());
96 + TestUtils.setField(meterStore, "clusterService", new TestClusterService());
97 + TestUtils.setField(meterStore, "mastershipService", new TestMastershipService());
98 + meterStore.activate();
99 +
100 + manager = new MeterManager();
101 + manager.store = meterStore;
102 + TestUtils.setField(manager, "storageService", new TestStorageService());
103 + injectEventDispatcher(manager, new TestEventDispatcher());
104 + service = manager;
105 + registry = manager;
106 +
107 + manager.activate();
108 +
109 + provider = new TestProvider(PID);
110 + providerService = registry.register(provider);
111 +
112 + appId = new TestApplicationId(0, "MeterManagerTest");
113 +
114 + assertTrue("provider should be registered",
115 + registry.getProviders().contains(provider.id()));
116 +
117 + Band band = DefaultBand.builder()
118 + .ofType(Band.Type.DROP)
119 + .withRate(500)
120 + .build();
121 +
122 + m1 = DefaultMeter.builder()
123 + .forDevice(did("1"))
124 + .fromApp(APP_ID)
125 + .withId(MeterId.meterId(1))
126 + .withUnit(Meter.Unit.KB_PER_SEC)
127 + .withBands(Collections.singletonList(band))
128 + .build();
129 +
130 + m2 = DefaultMeter.builder()
131 + .forDevice(did("2"))
132 + .fromApp(APP_ID)
133 + .withId(MeterId.meterId(2))
134 + .withUnit(Meter.Unit.KB_PER_SEC)
135 + .withBands(Collections.singletonList(band))
136 + .build();
137 +
138 + m1Request = DefaultMeterRequest.builder()
139 + .forDevice(did("1"))
140 + .fromApp(APP_ID)
141 + .withUnit(Meter.Unit.KB_PER_SEC)
142 + .withBands(Collections.singletonList(band));
143 +
144 + m2Request = DefaultMeterRequest.builder()
145 + .forDevice(did("2"))
146 + .fromApp(APP_ID)
147 + .withUnit(Meter.Unit.KB_PER_SEC)
148 + .withBands(Collections.singletonList(band));
149 +
150 +
151 + }
152 +
153 + @After
154 + public void tearDown() {
155 + registry.unregister(provider);
156 + assertFalse("provider should not be registered",
157 + registry.getProviders().contains(provider.id()));
158 +
159 + manager.deactivate();
160 + injectEventDispatcher(manager, null);
161 +
162 + }
163 +
164 + @Test
165 + public void testAddition() {
166 + manager.submit(m1Request.add());
167 +
168 + assertTrue("The meter was not added", manager.getAllMeters().size() == 1);
169 +
170 + assertThat(manager.getMeter(MeterId.meterId(1)), is(m1));
171 + }
172 +
173 + @Test
174 + public void testRemove() {
175 + manager.submit(m1Request.add());
176 + manager.withdraw(m1Request.remove(), m1.id());
177 +
178 + assertThat(manager.getMeter(MeterId.meterId(1)).state(),
179 + is(MeterState.PENDING_REMOVE));
180 +
181 + providerService.pushMeterMetrics(m1.deviceId(), Collections.emptyList());
182 +
183 + assertTrue("The meter was not removed", manager.getAllMeters().size() == 0);
184 +
185 + }
186 +
187 +
188 +
189 + public class TestApplicationId extends DefaultApplicationId {
190 + public TestApplicationId(int id, String name) {
191 + super(id, name);
192 + }
193 + }
194 +
195 + private class TestProvider extends AbstractProvider implements MeterProvider {
196 +
197 + protected TestProvider(ProviderId id) {
198 + super(PID);
199 + }
200 +
201 + @Override
202 + public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
203 + //Currently unused.
204 + }
205 +
206 + @Override
207 + public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
208 + meters.put(meterOp.meter().id(), meterOp.meter());
209 + }
210 + }
211 +
212 + private final class TestClusterService extends ClusterServiceAdapter {
213 +
214 + ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);
215 +
216 + @Override
217 + public ControllerNode getLocalNode() {
218 + return local;
219 + }
220 +
221 + @Override
222 + public Set<ControllerNode> getNodes() {
223 + return Sets.newHashSet();
224 + }
225 +
226 + }
227 +
228 + private class TestMastershipService extends MastershipServiceAdapter {
229 + @Override
230 + public NodeId getMasterFor(DeviceId deviceId) {
231 + return NID_LOCAL;
232 + }
233 + }
234 +}
...@@ -143,7 +143,9 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD ...@@ -143,7 +143,9 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD
143 // update the state of the meter. It will be pruned by observing 143 // update the state of the meter. It will be pruned by observing
144 // that it has been removed from the dataplane. 144 // that it has been removed from the dataplane.
145 try { 145 try {
146 - meters.put(meter.id(), data); 146 + if (meters.computeIfPresent(meter.id(), (k, v) -> data) == null) {
147 + future.complete(MeterStoreResult.success());
148 + }
147 } catch (StorageException e) { 149 } catch (StorageException e) {
148 future.completeExceptionally(e); 150 future.completeExceptionally(e);
149 } 151 }
...@@ -159,7 +161,9 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD ...@@ -159,7 +161,9 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD
159 161
160 MeterData data = new MeterData(meter, null, local); 162 MeterData data = new MeterData(meter, null, local);
161 try { 163 try {
162 - meters.put(meter.id(), data); 164 + if (meters.computeIfPresent(meter.id(), (k, v) -> data) == null) {
165 + future.complete(MeterStoreResult.fail(MeterFailReason.INVALID_METER));
166 + }
163 } catch (StorageException e) { 167 } catch (StorageException e) {
164 future.completeExceptionally(e); 168 future.completeExceptionally(e);
165 } 169 }
...@@ -227,6 +231,10 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD ...@@ -227,6 +231,10 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD
227 } 231 }
228 break; 232 break;
229 case ADDED: 233 case ADDED:
234 + if (local.equals(data.origin()) && data.meter().state() == MeterState.PENDING_ADD) {
235 + futures.remove(data.meter().id()).complete(MeterStoreResult.success());
236 + }
237 + break;
230 case REMOVED: 238 case REMOVED:
231 if (local.equals(data.origin()) && data.meter().state() == MeterState.PENDING_REMOVE) { 239 if (local.equals(data.origin()) && data.meter().state() == MeterState.PENDING_REMOVE) {
232 futures.remove(data.meter().id()).complete(MeterStoreResult.success()); 240 futures.remove(data.meter().id()).complete(MeterStoreResult.success());
......