Brian O'Connor

Started refactoring Intent Manager

Introduced IntentData and reworked APIs

Change-Id: I1fa437ceb1b72c4017ac2da1573bfbeb64c0632a
...@@ -15,35 +15,18 @@ ...@@ -15,35 +15,18 @@
15 */ 15 */
16 package org.onosproject.event; 16 package org.onosproject.event;
17 17
18 -import com.google.common.collect.Lists; 18 +import org.onlab.util.AbstractAccumulator;
19 -import org.slf4j.Logger;
20 -import org.slf4j.LoggerFactory;
21 19
22 -import java.util.List;
23 import java.util.Timer; 20 import java.util.Timer;
24 -import java.util.TimerTask;
25 -
26 -import static com.google.common.base.Preconditions.checkArgument;
27 -import static com.google.common.base.Preconditions.checkNotNull;
28 21
29 /** 22 /**
30 * Base implementation of an event accumulator. It allows triggering based on 23 * Base implementation of an event accumulator. It allows triggering based on
31 * event inter-arrival time threshold, maximum batch life threshold and maximum 24 * event inter-arrival time threshold, maximum batch life threshold and maximum
32 * batch size. 25 * batch size.
33 */ 26 */
34 -public abstract class AbstractEventAccumulator implements EventAccumulator { 27 +public abstract class AbstractEventAccumulator
35 - 28 + extends AbstractAccumulator<Event>
36 - private Logger log = LoggerFactory.getLogger(AbstractEventAccumulator.class); 29 + implements EventAccumulator {
37 -
38 - private final Timer timer;
39 - private final int maxEvents;
40 - private final int maxBatchMillis;
41 - private final int maxIdleMillis;
42 -
43 - private TimerTask idleTask = new ProcessorTask();
44 - private TimerTask maxTask = new ProcessorTask();
45 -
46 - private List<Event> events = Lists.newArrayList();
47 30
48 /** 31 /**
49 * Creates an event accumulator capable of triggering on the specified 32 * Creates an event accumulator capable of triggering on the specified
...@@ -59,108 +42,6 @@ public abstract class AbstractEventAccumulator implements EventAccumulator { ...@@ -59,108 +42,6 @@ public abstract class AbstractEventAccumulator implements EventAccumulator {
59 */ 42 */
60 protected AbstractEventAccumulator(Timer timer, int maxEvents, 43 protected AbstractEventAccumulator(Timer timer, int maxEvents,
61 int maxBatchMillis, int maxIdleMillis) { 44 int maxBatchMillis, int maxIdleMillis) {
62 - this.timer = checkNotNull(timer, "Timer cannot be null"); 45 + super(timer, maxEvents, maxBatchMillis, maxIdleMillis);
63 -
64 - checkArgument(maxEvents > 1, "Maximum number of events must be > 1");
65 - checkArgument(maxBatchMillis > 0, "Maximum millis must be positive");
66 - checkArgument(maxIdleMillis > 0, "Maximum idle millis must be positive");
67 -
68 - this.maxEvents = maxEvents;
69 - this.maxBatchMillis = maxBatchMillis;
70 - this.maxIdleMillis = maxIdleMillis;
71 - }
72 -
73 - @Override
74 - public void add(Event event) {
75 - idleTask = cancelIfActive(idleTask);
76 - events.add(event);
77 -
78 - // Did we hit the max event threshold?
79 - if (events.size() == maxEvents) {
80 - maxTask = cancelIfActive(maxTask);
81 - schedule(1);
82 - } else {
83 - // Otherwise, schedule idle task and if this is a first event
84 - // also schedule the max batch age task.
85 - idleTask = schedule(maxIdleMillis);
86 - if (events.size() == 1) {
87 - maxTask = schedule(maxBatchMillis);
88 - }
89 - }
90 - }
91 -
92 - // Schedules a new processor task given number of millis in the future.
93 - private TimerTask schedule(int millis) {
94 - TimerTask task = new ProcessorTask();
95 - timer.schedule(task, millis);
96 - return task;
97 - }
98 -
99 - // Cancels the specified task if it is active.
100 - private TimerTask cancelIfActive(TimerTask task) {
101 - if (task != null) {
102 - task.cancel();
103 - }
104 - return task;
105 - }
106 -
107 - // Task for triggering processing of accumulated events
108 - private class ProcessorTask extends TimerTask {
109 - @Override
110 - public void run() {
111 - try {
112 - idleTask = cancelIfActive(idleTask);
113 - maxTask = cancelIfActive(maxTask);
114 - processEvents(finalizeCurrentBatch());
115 - } catch (Exception e) {
116 - log.warn("Unable to process batch due to {}", e.getMessage());
117 - }
118 - }
119 - }
120 -
121 - // Demotes and returns the current batch of events and promotes a new one.
122 - private synchronized List<Event> finalizeCurrentBatch() {
123 - List<Event> toBeProcessed = events;
124 - events = Lists.newArrayList();
125 - return toBeProcessed;
126 - }
127 -
128 - /**
129 - * Returns the backing timer.
130 - *
131 - * @return backing timer
132 - */
133 - public Timer timer() {
134 - return timer;
135 - }
136 -
137 - /**
138 - * Returns the maximum number of events allowed to accumulate before
139 - * processing is triggered.
140 - *
141 - * @return max number of events
142 - */
143 - public int maxEvents() {
144 - return maxEvents;
145 - }
146 -
147 - /**
148 - * Returns the maximum number of millis allowed to expire since the first
149 - * event before processing is triggered.
150 - *
151 - * @return max number of millis a batch is allowed to last
152 - */
153 - public int maxBatchMillis() {
154 - return maxBatchMillis;
155 - }
156 -
157 - /**
158 - * Returns the maximum number of millis allowed to expire since the last
159 - * event arrival before processing is triggered.
160 - *
161 - * @return max number of millis since the last event
162 - */
163 - public int maxIdleMillis() {
164 - return maxIdleMillis;
165 } 46 }
166 } 47 }
......
...@@ -15,27 +15,11 @@ ...@@ -15,27 +15,11 @@
15 */ 15 */
16 package org.onosproject.event; 16 package org.onosproject.event;
17 17
18 -import java.util.List; 18 +import org.onlab.util.Accumulator;
19 19
20 /** 20 /**
21 * Abstraction of an accumulator capable of collecting events and at some 21 * Abstraction of an accumulator capable of collecting events and at some
22 * point in time triggers processing of all previously accumulated events. 22 * point in time triggers processing of all previously accumulated events.
23 */ 23 */
24 -public interface EventAccumulator { 24 +public interface EventAccumulator extends Accumulator<Event> {
25 -
26 - /**
27 - * Adds an event to the current batch. This operation may, or may not
28 - * trigger processing of the current batch of events.
29 - *
30 - * @param event event to be added to the current batch
31 - */
32 - void add(Event event);
33 -
34 - /**
35 - * Processes the specified list of accumulated events.
36 - *
37 - * @param events list of accumulated events
38 - */
39 - void processEvents(List<Event> events);
40 -
41 } 25 }
......
...@@ -36,7 +36,7 @@ public abstract class Intent { ...@@ -36,7 +36,7 @@ public abstract class Intent {
36 private final IntentId id; 36 private final IntentId id;
37 37
38 private final ApplicationId appId; 38 private final ApplicationId appId;
39 - private final String key; 39 + private final String key; // TODO make this a class
40 40
41 private final Collection<NetworkResource> resources; 41 private final Collection<NetworkResource> resources;
42 42
...@@ -156,4 +156,8 @@ public abstract class Intent { ...@@ -156,4 +156,8 @@ public abstract class Intent {
156 idGenerator = null; 156 idGenerator = null;
157 } 157 }
158 } 158 }
159 +
160 + public String key() {
161 + return key;
162 + }
159 } 163 }
......
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.intent;
17 +
18 +import com.google.common.collect.ImmutableList;
19 +import org.onosproject.store.Timestamp;
20 +
21 +import java.util.List;
22 +import java.util.Objects;
23 +
24 +/**
25 + * A wrapper class that contains an intents, its state, and other metadata for
26 + * internal use.
27 + */
28 +public class IntentData { //FIXME need to make this "immutable"
29 + // manager should be able to mutate a local copy while processing
30 + private Intent intent;
31 +
32 + private IntentState state;
33 + private Timestamp version;
34 +
35 + private List<Intent> installables;
36 +
37 + public IntentData(Intent intent, IntentState state, Timestamp version) {
38 + this.intent = intent;
39 + this.state = state;
40 + this.version = version;
41 + }
42 +
43 + // kryo constructor
44 + protected IntentData() {
45 + }
46 +
47 + public Intent intent() {
48 + return intent;
49 + }
50 +
51 + public IntentState state() {
52 + return state;
53 + }
54 +
55 + public String key() {
56 + return intent.key();
57 + }
58 +
59 + public void setState(IntentState newState) {
60 + this.state = newState;
61 + }
62 +
63 + public void setInstallables(List<Intent> installables) {
64 + this.installables = ImmutableList.copyOf(installables);
65 + }
66 +
67 + public List<Intent> installables() {
68 + return installables;
69 + }
70 +
71 + @Override
72 + public int hashCode() {
73 + return Objects.hash(intent, version);
74 + }
75 +
76 + @Override
77 + public boolean equals(Object obj) {
78 + if (this == obj) {
79 + return true;
80 + }
81 + if (obj == null || getClass() != obj.getClass()) {
82 + return false;
83 + }
84 + final IntentData other = (IntentData) obj;
85 + return Objects.equals(this.intent, other.intent)
86 + && Objects.equals(this.version, other.version);
87 + }
88 +}
...@@ -27,9 +27,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -27,9 +27,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
27 public final class IntentOperation { 27 public final class IntentOperation {
28 28
29 private final Type type; 29 private final Type type;
30 - private final IntentId intentId;
31 private final Intent intent; 30 private final Intent intent;
32 - //FIXME consider pulling the key out (we will hash based on key)
33 31
34 /** 32 /**
35 * Operation type. 33 * Operation type.
...@@ -62,12 +60,10 @@ public final class IntentOperation { ...@@ -62,12 +60,10 @@ public final class IntentOperation {
62 * Creates an intent operation. 60 * Creates an intent operation.
63 * 61 *
64 * @param type operation type 62 * @param type operation type
65 - * @param intentId identifier of the intent subject to the operation
66 * @param intent intent subject 63 * @param intent intent subject
67 */ 64 */
68 - IntentOperation(Type type, IntentId intentId, Intent intent) { 65 + public IntentOperation(Type type, Intent intent) {
69 this.type = checkNotNull(type); 66 this.type = checkNotNull(type);
70 - this.intentId = checkNotNull(intentId);
71 this.intent = intent; 67 this.intent = intent;
72 } 68 }
73 69
...@@ -86,7 +82,11 @@ public final class IntentOperation { ...@@ -86,7 +82,11 @@ public final class IntentOperation {
86 * @return intent identifier 82 * @return intent identifier
87 */ 83 */
88 public IntentId intentId() { 84 public IntentId intentId() {
89 - return intentId; 85 + return intent.id();
86 + }
87 +
88 + public String key() {
89 + return intent.key();
90 } 90 }
91 91
92 /** 92 /**
...@@ -101,7 +101,7 @@ public final class IntentOperation { ...@@ -101,7 +101,7 @@ public final class IntentOperation {
101 101
102 @Override 102 @Override
103 public int hashCode() { 103 public int hashCode() {
104 - return Objects.hash(type, intentId, intent); 104 + return Objects.hash(type, intent);
105 } 105 }
106 106
107 @Override 107 @Override
...@@ -114,7 +114,6 @@ public final class IntentOperation { ...@@ -114,7 +114,6 @@ public final class IntentOperation {
114 } 114 }
115 final IntentOperation other = (IntentOperation) obj; 115 final IntentOperation other = (IntentOperation) obj;
116 return Objects.equals(this.type, other.type) && 116 return Objects.equals(this.type, other.type) &&
117 - Objects.equals(this.intentId, other.intentId) &&
118 Objects.equals(this.intent, other.intent); 117 Objects.equals(this.intent, other.intent);
119 } 118 }
120 119
...@@ -123,7 +122,6 @@ public final class IntentOperation { ...@@ -123,7 +122,6 @@ public final class IntentOperation {
123 public String toString() { 122 public String toString() {
124 return toStringHelper(this) 123 return toStringHelper(this)
125 .add("type", type) 124 .add("type", type)
126 - .add("intentId", intentId)
127 .add("intent", intent) 125 .add("intent", intent)
128 .toString(); 126 .toString();
129 } 127 }
......
...@@ -31,7 +31,7 @@ import static org.onosproject.net.intent.IntentOperation.Type.WITHDRAW; ...@@ -31,7 +31,7 @@ import static org.onosproject.net.intent.IntentOperation.Type.WITHDRAW;
31 /** 31 /**
32 * Batch of intent submit/withdraw/replace operations. 32 * Batch of intent submit/withdraw/replace operations.
33 */ 33 */
34 -@Deprecated 34 +@Deprecated //DELETEME
35 public final class IntentOperations { 35 public final class IntentOperations {
36 36
37 private final List<IntentOperation> operations; 37 private final List<IntentOperation> operations;
...@@ -120,7 +120,7 @@ public final class IntentOperations { ...@@ -120,7 +120,7 @@ public final class IntentOperations {
120 */ 120 */
121 public Builder addSubmitOperation(Intent intent) { 121 public Builder addSubmitOperation(Intent intent) {
122 checkNotNull(intent, "Intent cannot be null"); 122 checkNotNull(intent, "Intent cannot be null");
123 - builder.add(new IntentOperation(SUBMIT, intent.id(), intent)); 123 + builder.add(new IntentOperation(SUBMIT, intent));
124 return this; 124 return this;
125 } 125 }
126 126
...@@ -134,7 +134,7 @@ public final class IntentOperations { ...@@ -134,7 +134,7 @@ public final class IntentOperations {
134 public Builder addReplaceOperation(IntentId oldIntentId, Intent newIntent) { 134 public Builder addReplaceOperation(IntentId oldIntentId, Intent newIntent) {
135 checkNotNull(oldIntentId, "Intent ID cannot be null"); 135 checkNotNull(oldIntentId, "Intent ID cannot be null");
136 checkNotNull(newIntent, "Intent cannot be null"); 136 checkNotNull(newIntent, "Intent cannot be null");
137 - builder.add(new IntentOperation(REPLACE, oldIntentId, newIntent)); 137 + builder.add(new IntentOperation(REPLACE, newIntent)); //FIXME
138 return this; 138 return this;
139 } 139 }
140 140
...@@ -146,7 +146,7 @@ public final class IntentOperations { ...@@ -146,7 +146,7 @@ public final class IntentOperations {
146 */ 146 */
147 public Builder addWithdrawOperation(IntentId intentId) { 147 public Builder addWithdrawOperation(IntentId intentId) {
148 checkNotNull(intentId, "Intent ID cannot be null"); 148 checkNotNull(intentId, "Intent ID cannot be null");
149 - builder.add(new IntentOperation(WITHDRAW, intentId, null)); 149 + builder.add(new IntentOperation(WITHDRAW, null)); //FIXME
150 return this; 150 return this;
151 } 151 }
152 152
...@@ -158,7 +158,7 @@ public final class IntentOperations { ...@@ -158,7 +158,7 @@ public final class IntentOperations {
158 */ 158 */
159 public Builder addUpdateOperation(IntentId intentId) { 159 public Builder addUpdateOperation(IntentId intentId) {
160 checkNotNull(intentId, "Intent ID cannot be null"); 160 checkNotNull(intentId, "Intent ID cannot be null");
161 - builder.add(new IntentOperation(UPDATE, intentId, null)); 161 + builder.add(new IntentOperation(UPDATE, null)); //FIXME
162 return this; 162 return this;
163 } 163 }
164 164
......
...@@ -30,7 +30,7 @@ public enum IntentState { ...@@ -30,7 +30,7 @@ public enum IntentState {
30 * Intents will also pass through this state when they are updated. 30 * Intents will also pass through this state when they are updated.
31 * </p> 31 * </p>
32 */ 32 */
33 - INSTALL_REQ, 33 + INSTALL_REQ, // TODO submit_REQ?
34 34
35 /** 35 /**
36 * Signifies that the intent is being compiled into installable intents. 36 * Signifies that the intent is being compiled into installable intents.
...@@ -66,7 +66,7 @@ public enum IntentState { ...@@ -66,7 +66,7 @@ public enum IntentState {
66 * previously failed to be installed. 66 * previously failed to be installed.
67 * </p> 67 * </p>
68 */ 68 */
69 - RECOMPILING, 69 + RECOMPILING, // TODO perhaps repurpose as BROKEN.
70 70
71 /** 71 /**
72 * Indicates that an application has requested that an intent be withdrawn. 72 * Indicates that an application has requested that an intent be withdrawn.
...@@ -92,5 +92,5 @@ public enum IntentState { ...@@ -92,5 +92,5 @@ public enum IntentState {
92 * Signifies that the intent has failed compiling, installing or 92 * Signifies that the intent has failed compiling, installing or
93 * recompiling states. 93 * recompiling states.
94 */ 94 */
95 - FAILED 95 + FAILED //TODO consider renaming to UNSAT.
96 } 96 }
......
...@@ -76,9 +76,9 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { ...@@ -76,9 +76,9 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
76 /** 76 /**
77 * Adds a new operation, which should be persisted and delegated. 77 * Adds a new operation, which should be persisted and delegated.
78 * 78 *
79 - * @param op operation 79 + * @param intent operation
80 */ 80 */
81 - default void add(IntentOperation op) {} //FIXME remove when impl. 81 + default void addPending(IntentData intent) {} //FIXME remove when impl.
82 82
83 /** 83 /**
84 * Checks to see whether the calling instance is the master for processing 84 * Checks to see whether the calling instance is the master for processing
......
...@@ -23,10 +23,10 @@ import org.onosproject.store.StoreDelegate; ...@@ -23,10 +23,10 @@ import org.onosproject.store.StoreDelegate;
23 public interface IntentStoreDelegate extends StoreDelegate<IntentEvent> { 23 public interface IntentStoreDelegate extends StoreDelegate<IntentEvent> {
24 24
25 /** 25 /**
26 - * Provides an intent operation that should be processed (compiled and 26 + * Provides an intent data object that should be processed (compiled and
27 * installed) by this manager. 27 * installed) by this manager.
28 * 28 *
29 - * @param op intent operation 29 + * @param intentData intent data object
30 */ 30 */
31 - void process(IntentOperation op); 31 + void process(IntentData intentData);
32 } 32 }
......
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.intent.impl;
17 +
18 +import com.google.common.collect.Maps;
19 +import org.onlab.util.AbstractAccumulator;
20 +import org.onosproject.net.intent.IntentData;
21 +
22 +import java.util.List;
23 +import java.util.Map;
24 +import java.util.Timer;
25 +
26 +/**
27 + * An accumulator for building batches of intent operations. Only one batch should
28 + * be in process per instance at a time.
29 + */
30 +public class IntentAccumulator extends AbstractAccumulator<IntentData> {
31 +
32 + private static final int DEFAULT_MAX_EVENTS = 1000;
33 + private static final int DEFAULT_MAX_IDLE_MS = 10;
34 + private static final int DEFAULT_MAX_BATCH_MS = 50;
35 +
36 + // FIXME: Replace with a system-wide timer instance;
37 + // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt
38 + private static final Timer TIMER = new Timer("intent-op-batching");
39 +
40 + /**
41 + * Creates an intent operation accumulator.
42 + */
43 + protected IntentAccumulator() {
44 + super(TIMER, DEFAULT_MAX_EVENTS, DEFAULT_MAX_BATCH_MS, DEFAULT_MAX_IDLE_MS);
45 + }
46 +
47 + @Override
48 + public void processEvents(List<IntentData> ops) {
49 + Map<String, IntentData> opMap = reduce(ops);
50 + // FIXME kick off the work
51 + //for (IntentData data : opMap.values()) {}
52 + }
53 +
54 + private Map<String, IntentData> reduce(List<IntentData> ops) {
55 + Map<String, IntentData> map = Maps.newHashMap();
56 + for (IntentData op : ops) {
57 + map.put(op.key(), op);
58 + }
59 + //TODO check the version... or maybe store will handle this.
60 + return map;
61 + }
62 +}
...@@ -37,6 +37,7 @@ import org.onosproject.net.intent.Intent; ...@@ -37,6 +37,7 @@ import org.onosproject.net.intent.Intent;
37 import org.onosproject.net.intent.IntentBatchDelegate; 37 import org.onosproject.net.intent.IntentBatchDelegate;
38 import org.onosproject.net.intent.IntentBatchService; 38 import org.onosproject.net.intent.IntentBatchService;
39 import org.onosproject.net.intent.IntentCompiler; 39 import org.onosproject.net.intent.IntentCompiler;
40 +import org.onosproject.net.intent.IntentData;
40 import org.onosproject.net.intent.IntentEvent; 41 import org.onosproject.net.intent.IntentEvent;
41 import org.onosproject.net.intent.IntentException; 42 import org.onosproject.net.intent.IntentException;
42 import org.onosproject.net.intent.IntentExtensionService; 43 import org.onosproject.net.intent.IntentExtensionService;
...@@ -128,6 +129,8 @@ public class IntentManager ...@@ -128,6 +129,8 @@ public class IntentManager
128 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate(); 129 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
129 private IdGenerator idGenerator; 130 private IdGenerator idGenerator;
130 131
132 + private final IntentAccumulator accumulator = new IntentAccumulator();
133 +
131 @Activate 134 @Activate
132 public void activate() { 135 public void activate() {
133 store.setDelegate(delegate); 136 store.setDelegate(delegate);
...@@ -154,32 +157,41 @@ public class IntentManager ...@@ -154,32 +157,41 @@ public class IntentManager
154 @Override 157 @Override
155 public void submit(Intent intent) { 158 public void submit(Intent intent) {
156 checkNotNull(intent, INTENT_NULL); 159 checkNotNull(intent, INTENT_NULL);
157 - execute(IntentOperations.builder(intent.appId()) 160 + IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
158 - .addSubmitOperation(intent).build()); 161 + //FIXME timestamp?
162 + store.addPending(data);
159 } 163 }
160 164
161 @Override 165 @Override
162 public void withdraw(Intent intent) { 166 public void withdraw(Intent intent) {
163 checkNotNull(intent, INTENT_NULL); 167 checkNotNull(intent, INTENT_NULL);
164 - execute(IntentOperations.builder(intent.appId()) 168 + IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
165 - .addWithdrawOperation(intent.id()).build()); 169 + //FIXME timestamp?
170 + store.addPending(data);
166 } 171 }
167 172
168 @Override 173 @Override
169 public void replace(IntentId oldIntentId, Intent newIntent) { 174 public void replace(IntentId oldIntentId, Intent newIntent) {
170 - checkNotNull(oldIntentId, INTENT_ID_NULL); 175 + throw new UnsupportedOperationException("replace is not implemented");
171 - checkNotNull(newIntent, INTENT_NULL);
172 - execute(IntentOperations.builder(newIntent.appId())
173 - .addReplaceOperation(oldIntentId, newIntent)
174 - .build());
175 } 176 }
176 177
177 @Override 178 @Override
178 public void execute(IntentOperations operations) { 179 public void execute(IntentOperations operations) {
179 - if (operations.operations().isEmpty()) { 180 + for (IntentOperation op : operations.operations()) {
180 - return; 181 + switch (op.type()) {
182 + case SUBMIT:
183 + case UPDATE:
184 + submit(op.intent());
185 + break;
186 + case WITHDRAW:
187 + withdraw(op.intent());
188 + break;
189 + //fallthrough
190 + case REPLACE:
191 + default:
192 + throw new UnsupportedOperationException("replace not supported");
193 + }
181 } 194 }
182 - batchService.addIntentOperations(operations);
183 } 195 }
184 196
185 @Override 197 @Override
...@@ -382,8 +394,8 @@ public class IntentManager ...@@ -382,8 +394,8 @@ public class IntentManager
382 } 394 }
383 395
384 @Override 396 @Override
385 - public void process(IntentOperation op) { 397 + public void process(IntentData data) {
386 - //FIXME 398 + accumulator.add(data);
387 } 399 }
388 } 400 }
389 401
...@@ -488,6 +500,7 @@ public class IntentManager ...@@ -488,6 +500,7 @@ public class IntentManager
488 } 500 }
489 } 501 }
490 502
503 + // TODO pull out the IntentUpdate inner classes
491 private class InstallRequest implements IntentUpdate { 504 private class InstallRequest implements IntentUpdate {
492 505
493 private final Intent intent; 506 private final Intent intent;
......
...@@ -17,19 +17,19 @@ package org.onosproject.store.trivial.impl; ...@@ -17,19 +17,19 @@ package org.onosproject.store.trivial.impl;
17 17
18 import com.google.common.collect.ImmutableSet; 18 import com.google.common.collect.ImmutableSet;
19 import com.google.common.collect.Lists; 19 import com.google.common.collect.Lists;
20 -
21 import org.apache.felix.scr.annotations.Activate; 20 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 21 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 22 import org.apache.felix.scr.annotations.Deactivate;
24 import org.apache.felix.scr.annotations.Service; 23 import org.apache.felix.scr.annotations.Service;
25 import org.onosproject.net.intent.BatchWrite; 24 import org.onosproject.net.intent.BatchWrite;
25 +import org.onosproject.net.intent.BatchWrite.Operation;
26 import org.onosproject.net.intent.Intent; 26 import org.onosproject.net.intent.Intent;
27 +import org.onosproject.net.intent.IntentData;
27 import org.onosproject.net.intent.IntentEvent; 28 import org.onosproject.net.intent.IntentEvent;
28 import org.onosproject.net.intent.IntentId; 29 import org.onosproject.net.intent.IntentId;
29 import org.onosproject.net.intent.IntentState; 30 import org.onosproject.net.intent.IntentState;
30 import org.onosproject.net.intent.IntentStore; 31 import org.onosproject.net.intent.IntentStore;
31 import org.onosproject.net.intent.IntentStoreDelegate; 32 import org.onosproject.net.intent.IntentStoreDelegate;
32 -import org.onosproject.net.intent.BatchWrite.Operation;
33 import org.onosproject.store.AbstractStore; 33 import org.onosproject.store.AbstractStore;
34 import org.slf4j.Logger; 34 import org.slf4j.Logger;
35 35
...@@ -38,8 +38,7 @@ import java.util.List; ...@@ -38,8 +38,7 @@ import java.util.List;
38 import java.util.Map; 38 import java.util.Map;
39 import java.util.concurrent.ConcurrentHashMap; 39 import java.util.concurrent.ConcurrentHashMap;
40 40
41 -import static com.google.common.base.Preconditions.checkArgument; 41 +import static com.google.common.base.Preconditions.*;
42 -import static com.google.common.base.Preconditions.checkState;
43 import static org.onosproject.net.intent.IntentState.WITHDRAWN; 42 import static org.onosproject.net.intent.IntentState.WITHDRAWN;
44 import static org.slf4j.LoggerFactory.getLogger; 43 import static org.slf4j.LoggerFactory.getLogger;
45 44
...@@ -50,10 +49,13 @@ public class SimpleIntentStore ...@@ -50,10 +49,13 @@ public class SimpleIntentStore
50 implements IntentStore { 49 implements IntentStore {
51 50
52 private final Logger log = getLogger(getClass()); 51 private final Logger log = getLogger(getClass());
52 +
53 + // current state maps FIXME.. make this a IntentData map
53 private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>(); 54 private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>();
54 private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>(); 55 private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>();
55 private final Map<IntentId, List<Intent>> installable = new ConcurrentHashMap<>(); 56 private final Map<IntentId, List<Intent>> installable = new ConcurrentHashMap<>();
56 57
58 + private final Map<String, IntentData> pending = new ConcurrentHashMap<>(); //String is "key"
57 59
58 @Activate 60 @Activate
59 public void activate() { 61 public void activate() {
...@@ -203,4 +205,19 @@ public class SimpleIntentStore ...@@ -203,4 +205,19 @@ public class SimpleIntentStore
203 } 205 }
204 return failed; 206 return failed;
205 } 207 }
208 +
209 + @Override
210 + public void addPending(IntentData data) {
211 + //FIXME need to compare versions
212 + pending.put(data.key(), data);
213 + checkNotNull(delegate, "Store delegate is not set")
214 + .process(data);
215 + }
216 + // FIXME!!! pending.remove(intent.key()); // TODO check version
217 +
218 +
219 + @Override
220 + public boolean isMaster(Intent intent) {
221 + return true;
222 + }
206 } 223 }
......
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.onlab.util;
17 +
18 +import com.google.common.collect.Lists;
19 +import org.slf4j.Logger;
20 +import org.slf4j.LoggerFactory;
21 +
22 +import java.util.List;
23 +import java.util.Timer;
24 +import java.util.TimerTask;
25 +
26 +import static com.google.common.base.Preconditions.checkArgument;
27 +import static com.google.common.base.Preconditions.checkNotNull;
28 +
29 +/**
30 + * Base implementation of an event accumulator. It allows triggering based on
31 + * event inter-arrival time threshold, maximum batch life threshold and maximum
32 + * batch size.
33 + */
34 +// FIXME refactor the names here
35 +public abstract class AbstractAccumulator<T> implements Accumulator<T> {
36 +
37 + private Logger log = LoggerFactory.getLogger(AbstractAccumulator.class);
38 +
39 + private final Timer timer;
40 + private final int maxEvents;
41 + private final int maxBatchMillis;
42 + private final int maxIdleMillis;
43 +
44 + private TimerTask idleTask = new ProcessorTask();
45 + private TimerTask maxTask = new ProcessorTask();
46 +
47 + private List<T> events = Lists.newArrayList();
48 +
49 + /**
50 + * Creates an event accumulator capable of triggering on the specified
51 + * thresholds.
52 + *
53 + * @param timer timer to use for scheduling check-points
54 + * @param maxEvents maximum number of events to accumulate before
55 + * processing is triggered
56 + * @param maxBatchMillis maximum number of millis allowed since the first
57 + * event before processing is triggered
58 + * @param maxIdleMillis maximum number millis between events before
59 + * processing is triggered
60 + */
61 + protected AbstractAccumulator(Timer timer, int maxEvents,
62 + int maxBatchMillis, int maxIdleMillis) {
63 + this.timer = checkNotNull(timer, "Timer cannot be null");
64 +
65 + checkArgument(maxEvents > 1, "Maximum number of events must be > 1");
66 + checkArgument(maxBatchMillis > 0, "Maximum millis must be positive");
67 + checkArgument(maxIdleMillis > 0, "Maximum idle millis must be positive");
68 +
69 + this.maxEvents = maxEvents;
70 + this.maxBatchMillis = maxBatchMillis;
71 + this.maxIdleMillis = maxIdleMillis;
72 + }
73 +
74 + @Override
75 + public void add(T event) {
76 + idleTask = cancelIfActive(idleTask);
77 + events.add(event);
78 +
79 + // Did we hit the max event threshold?
80 + if (events.size() == maxEvents) {
81 + maxTask = cancelIfActive(maxTask);
82 + schedule(1);
83 + } else {
84 + // Otherwise, schedule idle task and if this is a first event
85 + // also schedule the max batch age task.
86 + idleTask = schedule(maxIdleMillis);
87 + if (events.size() == 1) {
88 + maxTask = schedule(maxBatchMillis);
89 + }
90 + }
91 + }
92 +
93 + // Schedules a new processor task given number of millis in the future.
94 + private TimerTask schedule(int millis) {
95 + TimerTask task = new ProcessorTask();
96 + timer.schedule(task, millis);
97 + return task;
98 + }
99 +
100 + // Cancels the specified task if it is active.
101 + private TimerTask cancelIfActive(TimerTask task) {
102 + if (task != null) {
103 + task.cancel();
104 + }
105 + return task;
106 + }
107 +
108 + // Task for triggering processing of accumulated events
109 + private class ProcessorTask extends TimerTask {
110 + @Override
111 + public void run() {
112 + try {
113 + idleTask = cancelIfActive(idleTask);
114 + maxTask = cancelIfActive(maxTask);
115 + processEvents(finalizeCurrentBatch());
116 + } catch (Exception e) {
117 + log.warn("Unable to process batch due to {}", e.getMessage());
118 + }
119 + }
120 + }
121 +
122 + // Demotes and returns the current batch of events and promotes a new one.
123 + private synchronized List<T> finalizeCurrentBatch() {
124 + List<T> toBeProcessed = events;
125 + events = Lists.newArrayList();
126 + return toBeProcessed;
127 + }
128 +
129 + /**
130 + * Returns the backing timer.
131 + *
132 + * @return backing timer
133 + */
134 + public Timer timer() {
135 + return timer;
136 + }
137 +
138 + /**
139 + * Returns the maximum number of events allowed to accumulate before
140 + * processing is triggered.
141 + *
142 + * @return max number of events
143 + */
144 + public int maxEvents() {
145 + return maxEvents;
146 + }
147 +
148 + /**
149 + * Returns the maximum number of millis allowed to expire since the first
150 + * event before processing is triggered.
151 + *
152 + * @return max number of millis a batch is allowed to last
153 + */
154 + public int maxBatchMillis() {
155 + return maxBatchMillis;
156 + }
157 +
158 + /**
159 + * Returns the maximum number of millis allowed to expire since the last
160 + * event arrival before processing is triggered.
161 + *
162 + * @return max number of millis since the last event
163 + */
164 + public int maxIdleMillis() {
165 + return maxIdleMillis;
166 + }
167 +}
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.onlab.util;
17 +
18 +import java.util.List;
19 +
20 +/**
21 + * Abstraction of an accumulator capable of collecting events and at some
22 + * point in time triggers processing of all previously accumulated events.
23 + */
24 +public interface Accumulator<T> {
25 +
26 + /**
27 + * Adds an event to the current batch. This operation may, or may not
28 + * trigger processing of the current batch of events.
29 + *
30 + * @param event event to be added to the current batch
31 + */
32 + void add(T event);
33 +
34 + /**
35 + * Processes the specified list of accumulated events.
36 + *
37 + * @param events list of accumulated events
38 + */
39 + void processEvents(List<T> events);
40 +
41 +}