Madan Jampani

Work queue improvements

- Fixed logic to ensure only session to which task is currently assigned can complete it
- Support destroy method to reset work queue state
- Removed deprecated DistributedQueue primitive

Change-Id: I4e1d5be4eb142115130acf15ff34035cb9319a1a
Showing 18 changed files with 141 additions and 281 deletions
...@@ -19,7 +19,6 @@ import org.onosproject.store.service.WorkQueue; ...@@ -19,7 +19,6 @@ import org.onosproject.store.service.WorkQueue;
19 import org.onosproject.store.service.EventuallyConsistentMapBuilder; 19 import org.onosproject.store.service.EventuallyConsistentMapBuilder;
20 import org.onosproject.store.service.ConsistentMapBuilder; 20 import org.onosproject.store.service.ConsistentMapBuilder;
21 import org.onosproject.store.service.DistributedSetBuilder; 21 import org.onosproject.store.service.DistributedSetBuilder;
22 -import org.onosproject.store.service.DistributedQueueBuilder;
23 import org.onosproject.store.service.AtomicCounterBuilder; 22 import org.onosproject.store.service.AtomicCounterBuilder;
24 import org.onosproject.store.service.AtomicValueBuilder; 23 import org.onosproject.store.service.AtomicValueBuilder;
25 import org.onosproject.store.service.LeaderElectorBuilder; 24 import org.onosproject.store.service.LeaderElectorBuilder;
...@@ -47,11 +46,6 @@ public class VtnStorageServiceAdapter implements StorageService { ...@@ -47,11 +46,6 @@ public class VtnStorageServiceAdapter implements StorageService {
47 } 46 }
48 47
49 @Override 48 @Override
50 - public <E> DistributedQueueBuilder<E> queueBuilder() {
51 - return null;
52 - }
53 -
54 - @Override
55 public AtomicCounterBuilder atomicCounterBuilder() { 49 public AtomicCounterBuilder atomicCounterBuilder() {
56 return null; 50 return null;
57 } 51 }
......
...@@ -22,7 +22,6 @@ import org.onosproject.store.service.AsyncAtomicValue; ...@@ -22,7 +22,6 @@ import org.onosproject.store.service.AsyncAtomicValue;
22 import org.onosproject.store.service.AsyncConsistentMap; 22 import org.onosproject.store.service.AsyncConsistentMap;
23 import org.onosproject.store.service.AsyncDistributedSet; 23 import org.onosproject.store.service.AsyncDistributedSet;
24 import org.onosproject.store.service.AsyncLeaderElector; 24 import org.onosproject.store.service.AsyncLeaderElector;
25 -import org.onosproject.store.service.DistributedQueue;
26 import org.onosproject.store.service.WorkQueue; 25 import org.onosproject.store.service.WorkQueue;
27 import org.onosproject.store.service.Serializer; 26 import org.onosproject.store.service.Serializer;
28 27
...@@ -61,16 +60,6 @@ public interface DistributedPrimitiveCreator { ...@@ -61,16 +60,6 @@ public interface DistributedPrimitiveCreator {
61 <V> AsyncAtomicValue<V> newAsyncAtomicValue(String name, Serializer serializer); 60 <V> AsyncAtomicValue<V> newAsyncAtomicValue(String name, Serializer serializer);
62 61
63 /** 62 /**
64 - * Creates a new {@code DistributedQueue}.
65 - *
66 - * @param name queue name
67 - * @param serializer serializer to use for serializing/deserializing queue entries
68 - * @param <E> queue entry type
69 - * @return queue
70 - */
71 - <E> DistributedQueue<E> newDistributedQueue(String name, Serializer serializer);
72 -
73 - /**
74 * Creates a new {@code AsyncDistributedSet}. 63 * Creates a new {@code AsyncDistributedSet}.
75 * 64 *
76 * @param name set name 65 * @param name set name
......
...@@ -62,9 +62,9 @@ public interface DistributedPrimitive { ...@@ -62,9 +62,9 @@ public interface DistributedPrimitive {
62 VALUE, 62 VALUE,
63 63
64 /** 64 /**
65 - * Distributed queue. 65 + * Distributed work queue.
66 */ 66 */
67 - QUEUE, 67 + WORK_QUEUE,
68 68
69 /** 69 /**
70 * Leader elector. 70 * Leader elector.
......
1 -/*
2 - * Copyright 2015-present 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.store.service;
17 -
18 -import java.util.concurrent.CompletableFuture;
19 -
20 -/**
21 - * A distributed collection designed for holding elements prior to processing.
22 - * A queue provides insertion, extraction and inspection operations. The extraction operation
23 - * is designed to be non-blocking.
24 - *
25 - * @param <E> queue entry type
26 - */
27 -public interface DistributedQueue<E> extends DistributedPrimitive {
28 -
29 - /**
30 - * Returns total number of entries in the queue.
31 - * @return queue size
32 - */
33 - long size();
34 -
35 - /**
36 - * Returns true if queue has elements in it.
37 - * @return true is queue has elements, false otherwise
38 - */
39 - default boolean isEmpty() {
40 - return size() == 0;
41 - }
42 -
43 - /**
44 - * Inserts an entry into the queue.
45 - * @param entry entry to insert
46 - */
47 - void push(E entry);
48 -
49 - /**
50 - * If the queue is non-empty, an entry will be removed from the queue and the returned future
51 - * will be immediately completed with it. If queue is empty when this call is made, the returned
52 - * future will be eventually completed when an entry is added to the queue.
53 - * @return queue entry
54 - */
55 - CompletableFuture<E> pop();
56 -
57 - /**
58 - * Returns an entry from the queue without removing it. If the queue is empty returns null.
59 - * @return queue entry or null if queue is empty
60 - */
61 - E peek();
62 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present 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.store.service;
17 -
18 -/**
19 - * Builder for distributed queue.
20 - *
21 - * @param <E> type queue elements.
22 - */
23 -public interface DistributedQueueBuilder<E> {
24 -
25 - /**
26 - * Sets the name of the queue.
27 - * <p>
28 - * Each queue is identified by a unique name.
29 - * </p>
30 - * <p>
31 - * Note: This is a mandatory parameter.
32 - * </p>
33 - *
34 - * @param name name of the queue
35 - * @return this DistributedQueueBuilder for method chaining
36 - */
37 - DistributedQueueBuilder<E> withName(String name);
38 -
39 - /**
40 - * Sets a serializer that can be used to serialize
41 - * the elements pushed into the queue. The serializer
42 - * builder should be pre-populated with any classes that will be
43 - * put into the queue.
44 - * <p>
45 - * Note: This is a mandatory parameter.
46 - * </p>
47 - *
48 - * @param serializer serializer
49 - * @return this DistributedQueueBuilder for method chaining
50 - */
51 - DistributedQueueBuilder<E> withSerializer(Serializer serializer);
52 -
53 - /**
54 - * Builds a queue based on the configuration options
55 - * supplied to this builder.
56 - *
57 - * @return new distributed queue
58 - * @throws java.lang.RuntimeException if a mandatory parameter is missing
59 - */
60 - DistributedQueue<E> build();
61 -}
...@@ -52,14 +52,6 @@ public interface StorageService { ...@@ -52,14 +52,6 @@ public interface StorageService {
52 <E> DistributedSetBuilder<E> setBuilder(); 52 <E> DistributedSetBuilder<E> setBuilder();
53 53
54 /** 54 /**
55 - * Creates a new DistributedQueueBuilder.
56 - *
57 - * @param <E> queue entry type
58 - * @return builder for an distributed queue
59 - */
60 - <E> DistributedQueueBuilder<E> queueBuilder();
61 -
62 - /**
63 * Creates a new AtomicCounterBuilder. 55 * Creates a new AtomicCounterBuilder.
64 * 56 *
65 * @return atomic counter builder 57 * @return atomic counter builder
......
...@@ -39,7 +39,12 @@ import com.google.common.collect.ImmutableList; ...@@ -39,7 +39,12 @@ import com.google.common.collect.ImmutableList;
39 * 39 *
40 * @param <E> task payload type. 40 * @param <E> task payload type.
41 */ 41 */
42 -public interface WorkQueue<E> { 42 +public interface WorkQueue<E> extends DistributedPrimitive {
43 +
44 + @Override
45 + default DistributedPrimitive.Type primitiveType() {
46 + return DistributedPrimitive.Type.WORK_QUEUE;
47 + }
43 48
44 /** 49 /**
45 * Adds a collection of tasks to the work queue. 50 * Adds a collection of tasks to the work queue.
......
...@@ -35,11 +35,6 @@ public class StorageServiceAdapter implements StorageService { ...@@ -35,11 +35,6 @@ public class StorageServiceAdapter implements StorageService {
35 } 35 }
36 36
37 @Override 37 @Override
38 - public <E> DistributedQueueBuilder<E> queueBuilder() {
39 - return null;
40 - }
41 -
42 - @Override
43 public AtomicCounterBuilder atomicCounterBuilder() { 38 public AtomicCounterBuilder atomicCounterBuilder() {
44 return null; 39 return null;
45 } 40 }
......
...@@ -34,11 +34,6 @@ public class TestStorageService extends StorageServiceAdapter { ...@@ -34,11 +34,6 @@ public class TestStorageService extends StorageServiceAdapter {
34 } 34 }
35 35
36 @Override 36 @Override
37 - public <E> DistributedQueueBuilder<E> queueBuilder() {
38 - throw new UnsupportedOperationException("queueBuilder");
39 - }
40 -
41 - @Override
42 public AtomicCounterBuilder atomicCounterBuilder() { 37 public AtomicCounterBuilder atomicCounterBuilder() {
43 return TestAtomicCounter.builder(); 38 return TestAtomicCounter.builder();
44 } 39 }
......
1 -/*
2 - * Copyright 2016-present 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.store.primitives.impl;
17 -
18 -import org.onosproject.store.primitives.DistributedPrimitiveCreator;
19 -import org.onosproject.store.service.DistributedQueue;
20 -import org.onosproject.store.service.DistributedQueueBuilder;
21 -import org.onosproject.store.service.Serializer;
22 -
23 -import static com.google.common.base.Preconditions.checkArgument;
24 -import static com.google.common.base.Preconditions.checkState;
25 -
26 -/**
27 - * Default implementation of a {@code DistributedQueueBuilder}.
28 - *
29 - * @param <E> queue entry type
30 - */
31 -public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilder<E> {
32 -
33 - private final DistributedPrimitiveCreator primitiveCreator;
34 - private String name;
35 - private Serializer serializer;
36 -
37 - public DefaultDistributedQueueBuilder(DistributedPrimitiveCreator primitiveCreator) {
38 - this.primitiveCreator = primitiveCreator;
39 - }
40 -
41 - @Override
42 - public DistributedQueueBuilder<E> withName(String name) {
43 - checkArgument(name != null && !name.isEmpty());
44 - this.name = name;
45 - return this;
46 - }
47 -
48 - @Override
49 - public DistributedQueueBuilder<E> withSerializer(Serializer serializer) {
50 - checkArgument(serializer != null);
51 - this.serializer = serializer;
52 - return this;
53 - }
54 -
55 - private boolean validInputs() {
56 - return name != null && serializer != null;
57 - }
58 -
59 - @Override
60 - public DistributedQueue<E> build() {
61 - checkState(validInputs());
62 - return primitiveCreator.newDistributedQueue(name, serializer);
63 - }
64 -}
...@@ -30,6 +30,11 @@ public class DefaultDistributedWorkQueue<E> implements WorkQueue<E> { ...@@ -30,6 +30,11 @@ public class DefaultDistributedWorkQueue<E> implements WorkQueue<E> {
30 } 30 }
31 31
32 @Override 32 @Override
33 + public String name() {
34 + return backingQueue.name();
35 + }
36 +
37 + @Override
33 public CompletableFuture<Void> addMultiple(Collection<E> items) { 38 public CompletableFuture<Void> addMultiple(Collection<E> items) {
34 return backingQueue.addMultiple(items.stream() 39 return backingQueue.addMultiple(items.stream()
35 .map(serializer::encode) 40 .map(serializer::encode)
......
...@@ -29,9 +29,8 @@ import org.onosproject.store.service.AsyncAtomicValue; ...@@ -29,9 +29,8 @@ import org.onosproject.store.service.AsyncAtomicValue;
29 import org.onosproject.store.service.AsyncConsistentMap; 29 import org.onosproject.store.service.AsyncConsistentMap;
30 import org.onosproject.store.service.AsyncDistributedSet; 30 import org.onosproject.store.service.AsyncDistributedSet;
31 import org.onosproject.store.service.AsyncLeaderElector; 31 import org.onosproject.store.service.AsyncLeaderElector;
32 -import org.onosproject.store.service.DistributedQueue;
33 -import org.onosproject.store.service.WorkQueue;
34 import org.onosproject.store.service.Serializer; 32 import org.onosproject.store.service.Serializer;
33 +import org.onosproject.store.service.WorkQueue;
35 34
36 import com.google.common.base.Charsets; 35 import com.google.common.base.Charsets;
37 import com.google.common.collect.ImmutableSet; 36 import com.google.common.collect.ImmutableSet;
...@@ -84,11 +83,6 @@ public class FederatedDistributedPrimitiveCreator implements DistributedPrimitiv ...@@ -84,11 +83,6 @@ public class FederatedDistributedPrimitiveCreator implements DistributedPrimitiv
84 } 83 }
85 84
86 @Override 85 @Override
87 - public <E> DistributedQueue<E> newDistributedQueue(String name, Serializer serializer) {
88 - return getCreator(name).newDistributedQueue(name, serializer);
89 - }
90 -
91 - @Override
92 public AsyncLeaderElector newAsyncLeaderElector(String name) { 86 public AsyncLeaderElector newAsyncLeaderElector(String name) {
93 checkNotNull(name); 87 checkNotNull(name);
94 Map<PartitionId, AsyncLeaderElector> leaderElectors = 88 Map<PartitionId, AsyncLeaderElector> leaderElectors =
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.store.primitives.impl; 16 package org.onosproject.store.primitives.impl;
17 17
18 +import static org.onosproject.security.AppGuard.checkPermission;
19 +import static org.onosproject.security.AppPermission.Type.STORAGE_WRITE;
18 import static org.slf4j.LoggerFactory.getLogger; 20 import static org.slf4j.LoggerFactory.getLogger;
19 21
20 import java.util.Collection; 22 import java.util.Collection;
...@@ -44,9 +46,7 @@ import org.onosproject.store.service.AtomicCounterBuilder; ...@@ -44,9 +46,7 @@ import org.onosproject.store.service.AtomicCounterBuilder;
44 import org.onosproject.store.service.AtomicValueBuilder; 46 import org.onosproject.store.service.AtomicValueBuilder;
45 import org.onosproject.store.service.ConsistentMap; 47 import org.onosproject.store.service.ConsistentMap;
46 import org.onosproject.store.service.ConsistentMapBuilder; 48 import org.onosproject.store.service.ConsistentMapBuilder;
47 -import org.onosproject.store.service.DistributedQueueBuilder;
48 import org.onosproject.store.service.DistributedSetBuilder; 49 import org.onosproject.store.service.DistributedSetBuilder;
49 -import org.onosproject.store.service.WorkQueue;
50 import org.onosproject.store.service.EventuallyConsistentMapBuilder; 50 import org.onosproject.store.service.EventuallyConsistentMapBuilder;
51 import org.onosproject.store.service.LeaderElectorBuilder; 51 import org.onosproject.store.service.LeaderElectorBuilder;
52 import org.onosproject.store.service.MapInfo; 52 import org.onosproject.store.service.MapInfo;
...@@ -55,15 +55,13 @@ import org.onosproject.store.service.Serializer; ...@@ -55,15 +55,13 @@ import org.onosproject.store.service.Serializer;
55 import org.onosproject.store.service.StorageAdminService; 55 import org.onosproject.store.service.StorageAdminService;
56 import org.onosproject.store.service.StorageService; 56 import org.onosproject.store.service.StorageService;
57 import org.onosproject.store.service.TransactionContextBuilder; 57 import org.onosproject.store.service.TransactionContextBuilder;
58 +import org.onosproject.store.service.WorkQueue;
58 import org.onosproject.store.service.WorkQueueStats; 59 import org.onosproject.store.service.WorkQueueStats;
59 import org.slf4j.Logger; 60 import org.slf4j.Logger;
60 61
61 import com.google.common.collect.Maps; 62 import com.google.common.collect.Maps;
62 import com.google.common.util.concurrent.Futures; 63 import com.google.common.util.concurrent.Futures;
63 64
64 -import static org.onosproject.security.AppGuard.checkPermission;
65 -import static org.onosproject.security.AppPermission.Type.*;
66 -
67 /** 65 /**
68 * Implementation for {@code StorageService} and {@code StorageAdminService}. 66 * Implementation for {@code StorageService} and {@code StorageAdminService}.
69 */ 67 */
...@@ -137,12 +135,6 @@ public class StorageManager implements StorageService, StorageAdminService { ...@@ -137,12 +135,6 @@ public class StorageManager implements StorageService, StorageAdminService {
137 } 135 }
138 136
139 @Override 137 @Override
140 - public <E> DistributedQueueBuilder<E> queueBuilder() {
141 - checkPermission(STORAGE_WRITE);
142 - return new DefaultDistributedQueueBuilder<>(federatedPrimitiveCreator);
143 - }
144 -
145 - @Override
146 public AtomicCounterBuilder atomicCounterBuilder() { 138 public AtomicCounterBuilder atomicCounterBuilder() {
147 checkPermission(STORAGE_WRITE); 139 checkPermission(STORAGE_WRITE);
148 return new DefaultAtomicCounterBuilder(federatedPrimitiveCreator); 140 return new DefaultAtomicCounterBuilder(federatedPrimitiveCreator);
......
...@@ -49,10 +49,9 @@ import org.onosproject.store.service.AsyncConsistentMap; ...@@ -49,10 +49,9 @@ import org.onosproject.store.service.AsyncConsistentMap;
49 import org.onosproject.store.service.AsyncDistributedSet; 49 import org.onosproject.store.service.AsyncDistributedSet;
50 import org.onosproject.store.service.AsyncLeaderElector; 50 import org.onosproject.store.service.AsyncLeaderElector;
51 import org.onosproject.store.service.DistributedPrimitive.Status; 51 import org.onosproject.store.service.DistributedPrimitive.Status;
52 -import org.onosproject.store.service.DistributedQueue;
53 -import org.onosproject.store.service.WorkQueue;
54 import org.onosproject.store.service.PartitionClientInfo; 52 import org.onosproject.store.service.PartitionClientInfo;
55 import org.onosproject.store.service.Serializer; 53 import org.onosproject.store.service.Serializer;
54 +import org.onosproject.store.service.WorkQueue;
56 import org.slf4j.Logger; 55 import org.slf4j.Logger;
57 56
58 import com.google.common.base.Supplier; 57 import com.google.common.base.Supplier;
...@@ -160,11 +159,6 @@ public class StoragePartitionClient implements DistributedPrimitiveCreator, Mana ...@@ -160,11 +159,6 @@ public class StoragePartitionClient implements DistributedPrimitiveCreator, Mana
160 } 159 }
161 160
162 @Override 161 @Override
163 - public <E> DistributedQueue<E> newDistributedQueue(String name, Serializer serializer) {
164 - throw new UnsupportedOperationException();
165 - }
166 -
167 - @Override
168 public <E> WorkQueue<E> newWorkQueue(String name, Serializer serializer) { 162 public <E> WorkQueue<E> newWorkQueue(String name, Serializer serializer) {
169 AtomixWorkQueue workQueue = client.getResource(name, AtomixWorkQueue.class).join(); 163 AtomixWorkQueue workQueue = client.getResource(name, AtomixWorkQueue.class).join();
170 return new DefaultDistributedWorkQueue<>(workQueue, serializer); 164 return new DefaultDistributedWorkQueue<>(workQueue, serializer);
......
...@@ -18,6 +18,9 @@ package org.onosproject.store.primitives.resources.impl; ...@@ -18,6 +18,9 @@ package org.onosproject.store.primitives.resources.impl;
18 import static java.util.concurrent.Executors.newSingleThreadExecutor; 18 import static java.util.concurrent.Executors.newSingleThreadExecutor;
19 import static org.onlab.util.Tools.groupedThreads; 19 import static org.onlab.util.Tools.groupedThreads;
20 import static org.slf4j.LoggerFactory.getLogger; 20 import static org.slf4j.LoggerFactory.getLogger;
21 +import io.atomix.copycat.client.CopycatClient;
22 +import io.atomix.resource.AbstractResource;
23 +import io.atomix.resource.ResourceTypeInfo;
21 24
22 import java.util.Collection; 25 import java.util.Collection;
23 import java.util.List; 26 import java.util.List;
...@@ -34,22 +37,19 @@ import java.util.function.Consumer; ...@@ -34,22 +37,19 @@ import java.util.function.Consumer;
34 import org.onlab.util.AbstractAccumulator; 37 import org.onlab.util.AbstractAccumulator;
35 import org.onlab.util.Accumulator; 38 import org.onlab.util.Accumulator;
36 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Add; 39 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Add;
40 +import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Clear;
37 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Complete; 41 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Complete;
38 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Register; 42 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Register;
39 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Stats; 43 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Stats;
40 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Take; 44 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Take;
41 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Unregister; 45 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Unregister;
42 -import org.onosproject.store.service.WorkQueue;
43 import org.onosproject.store.service.Task; 46 import org.onosproject.store.service.Task;
47 +import org.onosproject.store.service.WorkQueue;
44 import org.onosproject.store.service.WorkQueueStats; 48 import org.onosproject.store.service.WorkQueueStats;
45 import org.slf4j.Logger; 49 import org.slf4j.Logger;
46 50
47 import com.google.common.collect.ImmutableList; 51 import com.google.common.collect.ImmutableList;
48 52
49 -import io.atomix.copycat.client.CopycatClient;
50 -import io.atomix.resource.AbstractResource;
51 -import io.atomix.resource.ResourceTypeInfo;
52 -
53 /** 53 /**
54 * Distributed resource providing the {@link WorkQueue} primitive. 54 * Distributed resource providing the {@link WorkQueue} primitive.
55 */ 55 */
...@@ -69,6 +69,18 @@ public class AtomixWorkQueue extends AbstractResource<AtomixWorkQueue> ...@@ -69,6 +69,18 @@ public class AtomixWorkQueue extends AbstractResource<AtomixWorkQueue>
69 } 69 }
70 70
71 @Override 71 @Override
72 + public String name() {
73 + return null;
74 + }
75 +
76 + @Override
77 + public CompletableFuture<Void> destroy() {
78 + executor.shutdown();
79 + timer.cancel();
80 + return client.submit(new Clear());
81 + }
82 +
83 + @Override
72 public CompletableFuture<AtomixWorkQueue> open() { 84 public CompletableFuture<AtomixWorkQueue> open() {
73 return super.open().thenApply(result -> { 85 return super.open().thenApply(result -> {
74 client.onStateChange(state -> { 86 client.onStateChange(state -> {
......
...@@ -15,6 +15,14 @@ ...@@ -15,6 +15,14 @@
15 */ 15 */
16 package org.onosproject.store.primitives.resources.impl; 16 package org.onosproject.store.primitives.resources.impl;
17 17
18 +import io.atomix.catalyst.buffer.BufferInput;
19 +import io.atomix.catalyst.buffer.BufferOutput;
20 +import io.atomix.catalyst.serializer.CatalystSerializable;
21 +import io.atomix.catalyst.serializer.SerializableTypeResolver;
22 +import io.atomix.catalyst.serializer.Serializer;
23 +import io.atomix.catalyst.serializer.SerializerRegistry;
24 +import io.atomix.copycat.Command;
25 +
18 import java.util.ArrayList; 26 import java.util.ArrayList;
19 import java.util.Collection; 27 import java.util.Collection;
20 import java.util.stream.Collectors; 28 import java.util.stream.Collectors;
...@@ -25,14 +33,6 @@ import org.onosproject.store.service.WorkQueueStats; ...@@ -25,14 +33,6 @@ import org.onosproject.store.service.WorkQueueStats;
25 33
26 import com.google.common.base.MoreObjects; 34 import com.google.common.base.MoreObjects;
27 35
28 -import io.atomix.catalyst.buffer.BufferInput;
29 -import io.atomix.catalyst.buffer.BufferOutput;
30 -import io.atomix.catalyst.serializer.CatalystSerializable;
31 -import io.atomix.catalyst.serializer.SerializableTypeResolver;
32 -import io.atomix.catalyst.serializer.Serializer;
33 -import io.atomix.catalyst.serializer.SerializerRegistry;
34 -import io.atomix.copycat.Command;
35 -
36 /** 36 /**
37 * {@link AtomixWorkQueue} resource state machine operations. 37 * {@link AtomixWorkQueue} resource state machine operations.
38 */ 38 */
...@@ -207,6 +207,24 @@ public final class AtomixWorkQueueCommands { ...@@ -207,6 +207,24 @@ public final class AtomixWorkQueueCommands {
207 } 207 }
208 } 208 }
209 209
210 + @SuppressWarnings("serial")
211 + public static class Clear implements Command<Void>, CatalystSerializable {
212 +
213 + @Override
214 + public void writeObject(BufferOutput<?> buffer, Serializer serializer) {
215 + }
216 +
217 + @Override
218 + public void readObject(BufferInput<?> buffer, Serializer serializer) {
219 + }
220 +
221 + @Override
222 + public String toString() {
223 + return MoreObjects.toStringHelper(getClass())
224 + .toString();
225 + }
226 + }
227 +
210 /** 228 /**
211 * Work queue command type resolver. 229 * Work queue command type resolver.
212 */ 230 */
...@@ -219,6 +237,7 @@ public final class AtomixWorkQueueCommands { ...@@ -219,6 +237,7 @@ public final class AtomixWorkQueueCommands {
219 registry.register(Add.class, -963); 237 registry.register(Add.class, -963);
220 registry.register(Complete.class, -964); 238 registry.register(Complete.class, -964);
221 registry.register(Stats.class, -965); 239 registry.register(Stats.class, -965);
240 + registry.register(Clear.class, -966);
222 } 241 }
223 } 242 }
224 } 243 }
......
...@@ -16,6 +16,14 @@ ...@@ -16,6 +16,14 @@
16 package org.onosproject.store.primitives.resources.impl; 16 package org.onosproject.store.primitives.resources.impl;
17 17
18 import static org.slf4j.LoggerFactory.getLogger; 18 import static org.slf4j.LoggerFactory.getLogger;
19 +import io.atomix.copycat.server.Commit;
20 +import io.atomix.copycat.server.Snapshottable;
21 +import io.atomix.copycat.server.StateMachineExecutor;
22 +import io.atomix.copycat.server.session.ServerSession;
23 +import io.atomix.copycat.server.session.SessionListener;
24 +import io.atomix.copycat.server.storage.snapshot.SnapshotReader;
25 +import io.atomix.copycat.server.storage.snapshot.SnapshotWriter;
26 +import io.atomix.resource.ResourceStateMachine;
19 27
20 import java.util.ArrayList; 28 import java.util.ArrayList;
21 import java.util.Collection; 29 import java.util.Collection;
...@@ -31,6 +39,7 @@ import java.util.stream.IntStream; ...@@ -31,6 +39,7 @@ import java.util.stream.IntStream;
31 39
32 import org.onlab.util.CountDownCompleter; 40 import org.onlab.util.CountDownCompleter;
33 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Add; 41 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Add;
42 +import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Clear;
34 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Complete; 43 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Complete;
35 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Register; 44 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Register;
36 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Stats; 45 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands.Stats;
...@@ -47,15 +56,6 @@ import com.google.common.collect.Maps; ...@@ -47,15 +56,6 @@ import com.google.common.collect.Maps;
47 import com.google.common.collect.Queues; 56 import com.google.common.collect.Queues;
48 import com.google.common.util.concurrent.AtomicLongMap; 57 import com.google.common.util.concurrent.AtomicLongMap;
49 58
50 -import io.atomix.copycat.server.Commit;
51 -import io.atomix.copycat.server.Snapshottable;
52 -import io.atomix.copycat.server.StateMachineExecutor;
53 -import io.atomix.copycat.server.session.ServerSession;
54 -import io.atomix.copycat.server.session.SessionListener;
55 -import io.atomix.copycat.server.storage.snapshot.SnapshotReader;
56 -import io.atomix.copycat.server.storage.snapshot.SnapshotWriter;
57 -import io.atomix.resource.ResourceStateMachine;
58 -
59 /** 59 /**
60 * State machine for {@link AtomixWorkQueue} resource. 60 * State machine for {@link AtomixWorkQueue} resource.
61 */ 61 */
...@@ -82,6 +82,7 @@ public class AtomixWorkQueueState extends ResourceStateMachine implements Sessi ...@@ -82,6 +82,7 @@ public class AtomixWorkQueueState extends ResourceStateMachine implements Sessi
82 executor.register(Add.class, (Consumer<Commit<Add>>) this::add); 82 executor.register(Add.class, (Consumer<Commit<Add>>) this::add);
83 executor.register(Take.class, this::take); 83 executor.register(Take.class, this::take);
84 executor.register(Complete.class, (Consumer<Commit<Complete>>) this::complete); 84 executor.register(Complete.class, (Consumer<Commit<Complete>>) this::complete);
85 + executor.register(Clear.class, (Consumer<Commit<Clear>>) this::clear);
85 } 86 }
86 87
87 protected WorkQueueStats stats(Commit<? extends Stats> commit) { 88 protected WorkQueueStats stats(Commit<? extends Stats> commit) {
...@@ -96,6 +97,17 @@ public class AtomixWorkQueueState extends ResourceStateMachine implements Sessi ...@@ -96,6 +97,17 @@ public class AtomixWorkQueueState extends ResourceStateMachine implements Sessi
96 } 97 }
97 } 98 }
98 99
100 + protected void clear(Commit<? extends Clear> commit) {
101 + unassignedTasks.forEach(TaskHolder::complete);
102 + unassignedTasks.clear();
103 + assignments.values().forEach(TaskAssignment::markComplete);
104 + assignments.clear();
105 + registeredWorkers.values().forEach(Commit::close);
106 + registeredWorkers.clear();
107 + activeTasksPerSession.clear();
108 + totalCompleted.set(0);
109 + }
110 +
99 protected void register(Commit<? extends Register> commit) { 111 protected void register(Commit<? extends Register> commit) {
100 long sessionId = commit.session().id(); 112 long sessionId = commit.session().id();
101 if (registeredWorkers.putIfAbsent(sessionId, commit) != null) { 113 if (registeredWorkers.putIfAbsent(sessionId, commit) != null) {
...@@ -172,7 +184,7 @@ public class AtomixWorkQueueState extends ResourceStateMachine implements Sessi ...@@ -172,7 +184,7 @@ public class AtomixWorkQueueState extends ResourceStateMachine implements Sessi
172 try { 184 try {
173 commit.operation().taskIds().forEach(taskId -> { 185 commit.operation().taskIds().forEach(taskId -> {
174 TaskAssignment assignment = assignments.get(taskId); 186 TaskAssignment assignment = assignments.get(taskId);
175 - if (assignment != null) { 187 + if (assignment != null && assignment.sessionId() == sessionId) {
176 assignments.remove(taskId).markComplete(); 188 assignments.remove(taskId).markComplete();
177 // bookkeeping 189 // bookkeeping
178 totalCompleted.incrementAndGet(); 190 totalCompleted.incrementAndGet();
......
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
15 */ 15 */
16 package org.onosproject.store.primitives.resources.impl; 16 package org.onosproject.store.primitives.resources.impl;
17 17
18 +import static org.junit.Assert.assertEquals;
19 +import static org.junit.Assert.assertNull;
20 +import static org.junit.Assert.assertTrue;
21 +import io.atomix.Atomix;
22 +import io.atomix.AtomixClient;
23 +import io.atomix.resource.ResourceType;
24 +
18 import java.time.Duration; 25 import java.time.Duration;
19 import java.util.Arrays; 26 import java.util.Arrays;
20 import java.util.UUID; 27 import java.util.UUID;
...@@ -23,10 +30,6 @@ import java.util.concurrent.Executor; ...@@ -23,10 +30,6 @@ import java.util.concurrent.Executor;
23 import java.util.concurrent.Executors; 30 import java.util.concurrent.Executors;
24 import java.util.concurrent.TimeUnit; 31 import java.util.concurrent.TimeUnit;
25 32
26 -import io.atomix.Atomix;
27 -import io.atomix.AtomixClient;
28 -import io.atomix.resource.ResourceType;
29 -
30 import org.junit.AfterClass; 33 import org.junit.AfterClass;
31 import org.junit.BeforeClass; 34 import org.junit.BeforeClass;
32 import org.junit.Test; 35 import org.junit.Test;
...@@ -36,10 +39,6 @@ import org.onosproject.store.service.WorkQueueStats; ...@@ -36,10 +39,6 @@ import org.onosproject.store.service.WorkQueueStats;
36 39
37 import com.google.common.util.concurrent.Uninterruptibles; 40 import com.google.common.util.concurrent.Uninterruptibles;
38 41
39 -import static org.junit.Assert.assertEquals;
40 -import static org.junit.Assert.assertNull;
41 -import static org.junit.Assert.assertTrue;
42 -
43 /** 42 /**
44 * Unit tests for {@link AtomixWorkQueue}. 43 * Unit tests for {@link AtomixWorkQueue}.
45 */ 44 */
...@@ -186,4 +185,54 @@ public class AtomixWorkQueueTest extends AtomixTestBase { ...@@ -186,4 +185,54 @@ public class AtomixWorkQueueTest extends AtomixTestBase {
186 185
187 Uninterruptibles.awaitUninterruptibly(latch2, 500, TimeUnit.MILLISECONDS); 186 Uninterruptibles.awaitUninterruptibly(latch2, 500, TimeUnit.MILLISECONDS);
188 } 187 }
188 +
189 + @Test
190 + public void testDestroy() {
191 + String queueName = UUID.randomUUID().toString();
192 + Atomix atomix1 = createAtomixClient();
193 + AtomixWorkQueue queue1 = atomix1.getResource(queueName, AtomixWorkQueue.class).join();
194 + byte[] item = DEFAULT_PAYLOAD;
195 + queue1.addOne(item).join();
196 +
197 + Atomix atomix2 = createAtomixClient();
198 + AtomixWorkQueue queue2 = atomix2.getResource(queueName, AtomixWorkQueue.class).join();
199 + byte[] task2 = DEFAULT_PAYLOAD;
200 + queue2.addOne(task2).join();
201 +
202 + WorkQueueStats stats = queue1.stats().join();
203 + assertEquals(stats.totalPending(), 2);
204 + assertEquals(stats.totalInProgress(), 0);
205 + assertEquals(stats.totalCompleted(), 0);
206 +
207 + queue2.destroy().join();
208 +
209 + stats = queue1.stats().join();
210 + assertEquals(stats.totalPending(), 0);
211 + assertEquals(stats.totalInProgress(), 0);
212 + assertEquals(stats.totalCompleted(), 0);
213 + }
214 +
215 + @Test
216 + public void testCompleteAttemptWithIncorrectSession() {
217 + String queueName = UUID.randomUUID().toString();
218 + Atomix atomix1 = createAtomixClient();
219 + AtomixWorkQueue queue1 = atomix1.getResource(queueName, AtomixWorkQueue.class).join();
220 + byte[] item = DEFAULT_PAYLOAD;
221 + queue1.addOne(item).join();
222 +
223 + Task<byte[]> task = queue1.take().join();
224 + String taskId = task.taskId();
225 +
226 + // Create another client and get a handle to the same queue.
227 + Atomix atomix2 = createAtomixClient();
228 + AtomixWorkQueue queue2 = atomix2.getResource(queueName, AtomixWorkQueue.class).join();
229 +
230 + // Attempt completing the task with new client and verify task is not completed
231 + queue2.complete(taskId).join();
232 +
233 + WorkQueueStats stats = queue1.stats().join();
234 + assertEquals(stats.totalPending(), 0);
235 + assertEquals(stats.totalInProgress(), 1);
236 + assertEquals(stats.totalCompleted(), 0);
237 + }
189 } 238 }
......