BUG-9079 Make PCEP session recoverable from exception
[bgpcep.git] / pcep / topology / topology-spi / src / main / java / org / opendaylight / bgpcep / pcep / topology / spi / AbstractInstructionExecutor.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.bgpcep.pcep.topology.spi;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import org.opendaylight.bgpcep.programming.spi.Instruction;
17 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
18 import org.opendaylight.bgpcep.programming.spi.SchedulerException;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev150720.InstructionStatus;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev150720.SubmitInstructionInput;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev150720.submit.instruction.output.result.FailureCase;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev150720.submit.instruction.output.result.FailureCaseBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 public abstract class AbstractInstructionExecutor implements FutureCallback<Instruction> {
28
29     private static final class InstructionCallback implements FutureCallback<OperationResult> {
30
31         private final Instruction insn;
32
33         public InstructionCallback(final Instruction insn) {
34             this.insn = insn;
35         }
36
37         @Override
38         public void onSuccess(final OperationResult result) {
39             if (result.getFailure() != null) {
40                 switch (result.getFailure()) {
41                 case Failed:
42                 case NoAck:
43                     this.insn.executionCompleted(InstructionStatus.Failed, null);
44                     break;
45                 case Unsent:
46                     this.insn.executionCompleted(InstructionStatus.Cancelled, null);
47                     break;
48                 default:
49                     break;
50                 }
51             } else {
52                 this.insn.executionCompleted(InstructionStatus.Successful, null);
53             }
54         }
55
56         @Override
57         public void onFailure(final Throwable t) {
58             this.insn.executionCompleted(InstructionStatus.Failed, null);
59         }
60     }
61
62     private static final Logger LOG = LoggerFactory.getLogger(AbstractInstructionExecutor.class);
63     private final SubmitInstructionInput input;
64
65     protected AbstractInstructionExecutor(final SubmitInstructionInput input) {
66         this.input = requireNonNull(input);
67     }
68
69     public final SubmitInstructionInput getInput() {
70         return this.input;
71     }
72
73     public static FailureCase schedule(final InstructionScheduler scheduler, final AbstractInstructionExecutor fwd) {
74         final ListenableFuture<Instruction> s;
75         try {
76             s = scheduler.scheduleInstruction(fwd.getInput());
77         } catch (final SchedulerException e) {
78             LOG.info("Instuction {} failed to schedule", e.getMessage(), e);
79             return new FailureCaseBuilder().setFailure(e.getFailure()).build();
80         }
81         Futures.addCallback(s, fwd, MoreExecutors.directExecutor());
82         return null;
83     }
84
85     protected abstract ListenableFuture<OperationResult> invokeOperation();
86
87     @Override
88     public void onSuccess(final Instruction insn) {
89         if (insn.checkedExecutionStart()) {
90             final ListenableFuture<OperationResult> s = invokeOperation();
91             Futures.addCallback(s, new InstructionCallback(insn), MoreExecutors.directExecutor());
92         }
93     }
94
95     @Override
96     public void onFailure(final Throwable t) {
97         LOG.debug("Instruction {} cancelled", this.input, t);
98     }
99 }