BUG-218: expose instruction status in MD-SAL 15/3715/2
authorRobert Varga <rovarga@cisco.com>
Fri, 13 Dec 2013 16:58:00 +0000 (17:58 +0100)
committerRobert Varga <rovarga@cisco.com>
Fri, 13 Dec 2013 18:04:29 +0000 (19:04 +0100)
Change-Id: I03f9c9562b314a6da264acab418a856daadc7217
Signed-off-by: Robert Varga <rovarga@cisco.com>
programming/api/src/main/yang/programming.yang
programming/controller-config/src/main/resources/initial/30-programming.conf
programming/impl-config/src/main/java/org/opendaylight/controller/config/yang/programming/impl/InstructionSchedulerImplModule.java
programming/impl-config/src/main/yang/config-programming-impl.yang
programming/impl/src/main/java/org/opendaylight/bgpcep/programming/impl/InstructionImpl.java
programming/impl/src/main/java/org/opendaylight/bgpcep/programming/impl/ProgrammingServiceImpl.java
programming/impl/src/main/java/org/opendaylight/bgpcep/programming/impl/QueueInstruction.java [new file with mode: 0644]

index 0a975540e2272befb84e9502761b9659c72969e8..7a3c54b264d5718d01de9c2c6a4d5ad9c9bda111 100644 (file)
@@ -340,7 +340,7 @@ module programming {
        }
 
        container instruction-queue {
-               list instructions {
+               list instruction {
                        leaf id {
                                type instruction-id;
                                mandatory true;
index 8ca07b776f3d4e71009316adc36f95480478edcd..8f469007e694346f04ac341938da10bc83eb67e3 100644 (file)
@@ -2,6 +2,10 @@
         <module>
                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:programming:impl">prefix:instruction-scheduler-impl</type>
                 <name>global-instruction-scheduler</name>
+               <data-provider>
+                       <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+                       <name>binding-data-broker</name>
+               </data-provider>
                <notification-service>
                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
                        <name>binding-notification-broker</name>
index 1138f39e0f3aad9352434057c573349540c6b877..fe19cc6a797e71ee990afcdee0a86ed96ee6b0b5 100644 (file)
@@ -50,7 +50,7 @@ org.opendaylight.controller.config.yang.programming.impl.AbstractInstructionSche
        public java.lang.AutoCloseable createInstance() {
                final ListeningExecutorService exec = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
 
-               final ProgrammingServiceImpl inst = new ProgrammingServiceImpl(getNotificationServiceDependency(), exec, getTimerDependency());
+               final ProgrammingServiceImpl inst = new ProgrammingServiceImpl(getDataProviderDependency(), getNotificationServiceDependency(), exec, getTimerDependency());
 
                final RpcRegistration<ProgrammingService> reg = getRpcRegistryDependency().addRpcImplementation(ProgrammingService.class, inst);
 
index faf59508fe38e20b2b3c244313bff160614626a3..78f6241f230b576ebead7c76585e1d96c135bb60 100644 (file)
@@ -39,6 +39,14 @@ module config-programming-impl {
         case instruction-scheduler-impl {
             when "/config:modules/config:module/config:type = 'instruction-scheduler-impl'";
 
+            container data-provider {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-data-broker;
+                    }
+                }
+            }
             container notification-service {
                 uses config:service-ref {
                     refine type {
index 7623f36b54886e365e01e19409d55f94990427eb..e342405ee2fa252c54f7afc6091625ca636a35fa 100644 (file)
@@ -17,11 +17,9 @@ import javax.annotation.concurrent.GuardedBy;
 
 import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
 import org.opendaylight.bgpcep.programming.spi.Instruction;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.CancelFailure;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatusChangedBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.UncancellableInstruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.DetailsBuilder;
@@ -36,21 +34,21 @@ import com.google.common.util.concurrent.SettableFuture;
 final class InstructionImpl implements Instruction {
        private static final Logger LOG = LoggerFactory.getLogger(InstructionImpl.class);
        private final List<InstructionImpl> dependants = new ArrayList<>();
-       private SettableFuture<ExecutionResult<Details>> executionFuture;
        private final SettableFuture<Instruction> schedulingFuture;
        private final List<InstructionImpl> dependencies;
-       private final NotificationProviderService notifs;
+       private final QueueInstruction queue;
        private final InstructionId id;
-       private volatile InstructionStatus status = InstructionStatus.Queued;
+       private SettableFuture<ExecutionResult<Details>> executionFuture;
+       private InstructionStatus status = InstructionStatus.Queued;
        private Details heldUpDetails;
        private Timeout timeout;
 
-       InstructionImpl(final SettableFuture<Instruction> future, final InstructionId id, final List<InstructionImpl> dependencies, final Timeout timeout, final NotificationProviderService notifs) {
+       InstructionImpl(final QueueInstruction queue, final SettableFuture<Instruction> future, final InstructionId id, final List<InstructionImpl> dependencies, final Timeout timeout) {
                this.schedulingFuture = Preconditions.checkNotNull(future);
-               this.id = Preconditions.checkNotNull(id);
                this.dependencies = Preconditions.checkNotNull(dependencies);
                this.timeout = Preconditions.checkNotNull(timeout);
-               this.notifs = Preconditions.checkNotNull(notifs);
+               this.queue = Preconditions.checkNotNull(queue);
+               this.id = Preconditions.checkNotNull(id);
        }
 
        InstructionId getId() {
@@ -67,7 +65,7 @@ final class InstructionImpl implements Instruction {
                LOG.debug("Instruction {} transitioned to status {}", id, status);
 
                // Send out a notification
-               this.notifs.publish(new InstructionStatusChangedBuilder().setId(id).setStatus(status).setDetails(details).build());
+               this.queue.instructionUpdated(status, details);
 
                switch (status) {
                case Cancelled:
index 209dcf3127cc4c9796c0670562ea1177c34bba42..1c6c89577b8af779dc50e198d763a41480c46d8d 100644 (file)
@@ -12,9 +12,7 @@ import io.netty.util.Timer;
 import io.netty.util.TimerTask;
 
 import java.math.BigInteger;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Deque;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -22,8 +20,6 @@ import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
-import javax.annotation.concurrent.GuardedBy;
-
 import org.opendaylight.bgpcep.programming.NanotimeUtil;
 import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
 import org.opendaylight.bgpcep.programming.spi.Instruction;
@@ -31,6 +27,8 @@ import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
 import org.opendaylight.bgpcep.programming.spi.SchedulerException;
 import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.CancelInstructionInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.CancelInstructionOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.CancelInstructionOutputBuilder;
@@ -40,13 +38,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programm
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.DeadOnArrival;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.DuplicateInstructionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionQueue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionQueueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatusChangedBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.Nanotime;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.ProgrammingService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.SubmitInstructionInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.UnknownInstruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.UnknownPreconditionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.queue.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.queue.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.queue.InstructionsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure._case.FailureBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,22 +64,63 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.SettableFuture;
 
-public final class ProgrammingServiceImpl implements InstructionScheduler, ProgrammingService, AutoCloseable {
+public final class ProgrammingServiceImpl implements AutoCloseable, InstructionScheduler, ProgrammingService {
        private static final Logger LOG = LoggerFactory.getLogger(ProgrammingServiceImpl.class);
 
        private final Map<InstructionId, InstructionImpl> insns = new HashMap<>();
-
-       @GuardedBy("this")
-       private final Deque<InstructionImpl> readyQueue = new ArrayDeque<>();
-
+       private final InstanceIdentifier<InstructionQueue> qid;
        private final NotificationProviderService notifs;
        private final ListeningExecutorService executor;
+       private final DataProviderService dataProvider;
        private final Timer timer;
 
-       public ProgrammingServiceImpl(final NotificationProviderService notifs, final ListeningExecutorService executor, final Timer timer) {
+       private final class InstructionPusher implements QueueInstruction {
+               private final InstructionsBuilder builder = new InstructionsBuilder();
+
+               InstructionPusher(final InstructionId id, final Nanotime deadline) {
+                       builder.setDeadline(deadline);
+                       builder.setId(id);
+                       builder.setKey(new InstructionsKey(id));
+                       builder.setStatus(InstructionStatus.Queued);
+               }
+
+               @Override
+               public void instructionUpdated(final InstructionStatus status, final Details details) {
+                       if (!status.equals(builder.getStatus())) {
+                               builder.setStatus(status);
+
+                               final DataModificationTransaction t = dataProvider.beginTransaction();
+                               t.putOperationalData(InstanceIdentifier.builder(qid).child(
+                                               org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.queue.Instruction.class,
+                                               new InstructionKey(builder.getId())).build(), builder.build());
+                               t.commit();
+                       }
+
+                       notifs.publish(new InstructionStatusChangedBuilder().setId(builder.getId()).setStatus(status).setDetails(details).build());
+               }
+
+               @Override
+               public void instructionRemoved() {
+                       final DataModificationTransaction t = dataProvider.beginTransaction();
+                       t.removeOperationalData(InstanceIdentifier.builder(qid).child(
+                                       org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.queue.Instruction.class,
+                                       new InstructionKey(builder.getId())).build());
+                       t.commit();
+               }
+       }
+
+       public ProgrammingServiceImpl(final DataProviderService dataProvider, final NotificationProviderService notifs, final ListeningExecutorService executor, final Timer timer) {
+               this.dataProvider = Preconditions.checkNotNull(dataProvider);
                this.notifs = Preconditions.checkNotNull(notifs);
                this.executor = Preconditions.checkNotNull(executor);
                this.timer = Preconditions.checkNotNull(timer);
+               qid = InstanceIdentifier.builder(InstructionQueue.class).toInstance();
+
+               final DataModificationTransaction t = dataProvider.beginTransaction();
+               Preconditions.checkState(t.readOperationalData(qid) == null, "Conflicting instruction queue found");
+
+               t.putOperationalData(qid, new InstructionQueueBuilder().build());
+               t.commit();
        }
 
        @Override
@@ -222,7 +269,7 @@ public final class ProgrammingServiceImpl implements InstructionScheduler, Progr
 
                // Put it into the instruction list
                final SettableFuture<Instruction> ret = SettableFuture.create();
-               final InstructionImpl i = new InstructionImpl(ret, input.getId(), dependencies, t, notifs);
+               final InstructionImpl i = new InstructionImpl(new InstructionPusher(id, input.getDeadline()), ret, id, dependencies, t);
                this.insns.put(id, i);
 
                // Attach it into its dependencies
@@ -267,8 +314,6 @@ public final class ProgrammingServiceImpl implements InstructionScheduler, Progr
        private synchronized void tryScheduleInstruction(final InstructionImpl i) {
                final ListenableFuture<ExecutionResult<Details>> f = i.ready();
                if (f != null) {
-                       this.readyQueue.add(i);
-
                        Futures.addCallback(f, new FutureCallback<ExecutionResult<Details>>() {
                                @Override
                                public void onSuccess(final ExecutionResult<Details> result) {
@@ -286,8 +331,14 @@ public final class ProgrammingServiceImpl implements InstructionScheduler, Progr
 
        @Override
        public synchronized void close() {
-               for (InstructionImpl i : readyQueue) {
-                       i.tryCancel(null);
+               try {
+                       for (InstructionImpl i : insns.values()) {
+                               i.tryCancel(null);
+                       }
+               } finally {
+                       final DataModificationTransaction t = dataProvider.beginTransaction();
+                       t.removeOperationalData(qid);
+                       t.commit();
                }
        }
 }
diff --git a/programming/impl/src/main/java/org/opendaylight/bgpcep/programming/impl/QueueInstruction.java b/programming/impl/src/main/java/org/opendaylight/bgpcep/programming/impl/QueueInstruction.java
new file mode 100644 (file)
index 0000000..c8c3bd4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.programming.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.Details;
+
+/**
+ *
+ */
+interface QueueInstruction {
+       void instructionUpdated(InstructionStatus status, Details details);
+       void instructionRemoved();
+}