2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.openflowplugin.openflow.md.core.session;
10 import com.google.common.base.Preconditions;
11 import java.math.BigInteger;
12 import java.util.concurrent.Callable;
13 import java.util.concurrent.Future;
14 import java.util.concurrent.TimeUnit;
15 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
16 import org.opendaylight.openflowplugin.openflow.md.core.MessageFactory;
17 import org.opendaylight.openflowplugin.openflow.md.util.RoleUtil;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
22 import org.opendaylight.yangtools.yang.common.RpcResult;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * push role to device - basic step:<br/>
29 * <li>here we read generationId from device and</li>
30 * <li>push role request with incremented generationId</li>
31 * <li>{@link #call()} returns true if role request was successful</li>
34 final class RolePushTask implements Callable<Boolean> {
36 public static final Logger LOG = LoggerFactory
37 .getLogger(RolePushTask.class);
39 public static final long TIMEOUT = 2000;
40 public static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
42 private SessionContext session;
44 private int retryCounter;
50 public RolePushTask(OfpRole role, SessionContext session) {
51 Preconditions.checkNotNull("OfpRole can not be empty.", role);
52 Preconditions.checkNotNull("Session context can not be empty.", session);
54 this.session = session;
58 * @return the retryCounter
60 public int getRetryCounter() {
65 * @return the priority
67 public int getPriority() {
72 * @param priority the priority to set
74 public void setPriority(int priority) {
75 this.priority = priority;
79 public Boolean call() throws RolePushException {
80 if (!session.isValid()) {
81 String msg = "giving up role change: current session is invalid";
83 throw new RolePushException(msg);
86 // adopt actual generationId from device (first shot failed and this is retry)
87 BigInteger generationId = null;
89 generationId = RoleUtil.readGenerationIdFromDevice(session).get(TIMEOUT, TIMEOUT_UNIT);
90 } catch (Exception e) {
91 LOG.debug("generationId request failed: ", e);
94 if (generationId == null) {
95 String msg = "giving up role change: current generationId can not be read";
97 throw new RolePushException(msg);
100 generationId = RoleUtil.getNextGenerationId(generationId);
102 // try to possess role on device
103 Future<RpcResult<RoleRequestOutput>> roleReply = RoleUtil.sendRoleChangeRequest(session, role, generationId);
104 // flush election result with barrier
105 BarrierInput barrierInput = MessageFactory.createBarrier(
106 session.getFeatures().getVersion(), session.getNextXid());
107 Future<RpcResult<BarrierOutput>> barrierResult = session.getPrimaryConductor().getConnectionAdapter().barrier(barrierInput);
109 barrierResult.get(TIMEOUT, TIMEOUT_UNIT);
110 } catch (Exception e) {
111 String msg = String.format("giving up role change: barrier after role change failed: %s", e.getMessage());
113 throw new RolePushException(msg);
115 // after barrier replied there must be election result or error
117 roleReply.get(0, TimeUnit.MILLISECONDS);
118 } catch (Exception e) {
119 // no election result received - let's retry
124 // here we expect that role on device is successfully possessed