Open Kilda Java Documentation
BatchRecord.java
Go to the documentation of this file.
1 /* Copyright 2018 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.floodlight.service.batch;
17 
20 
21 import net.floodlightcontroller.core.IOFSwitch;
22 import org.projectfloodlight.openflow.protocol.OFMessage;
23 import org.projectfloodlight.openflow.protocol.OFType;
24 import org.projectfloodlight.openflow.types.DatapathId;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 
28 import java.util.HashMap;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Map;
32 
33 class BatchRecord {
34  private static final Logger log = LoggerFactory.getLogger(BatchRecord.class);
35 
36  private final SwitchUtils switchUtils;
37 
38  private final List<OfPendingMessage> batch;
39  private final LinkedList<OfPendingMessage> barriers;
40  private boolean errors = false;
41  private boolean complete = false;
42 
43  BatchRecord(SwitchUtils switchUtils, List<OfPendingMessage> batch) {
44  this.switchUtils = switchUtils;
45  this.batch = batch;
46  this.barriers = new LinkedList<>();
47  }
48 
49  void write() throws OFInstallException {
50  Map<DatapathId, IOFSwitch> affectedSwitches = writePayload();
51  writeBarriers(affectedSwitches);
52 
53  complete = 0 == barriers.size();
54 
55  log.debug("Write {}(+{}) messages", batch.size(), barriers.size());
56  }
57 
58  boolean handleResponse(OFMessage response) {
59  boolean match = true;
60 
61  if (recordResponse(barriers, response)) {
62  log.debug("Have barrier message response");
63  updateBarriers();
64  } else if (recordResponse(batch, response)) {
65  log.debug(
66  "Have response for some of payload messages (xId: {}, type: {})",
67  response.getXid(), response.getType());
68  errors = OFType.ERROR == response.getType();
69  } else {
70  match = false;
71  }
72 
73  return match;
74  }
75 
76  private Map<DatapathId, IOFSwitch> writePayload() throws OFInstallException {
77  HashMap<DatapathId, IOFSwitch> affectedSwitches = new HashMap<>();
78 
79  for (OfPendingMessage record : batch) {
80  DatapathId dpId = record.getDpId();
81  IOFSwitch sw = affectedSwitches.get(dpId);
82  if (sw == null) {
83  sw = switchUtils.lookupSwitch(dpId);
84  affectedSwitches.put(dpId, sw);
85  }
86 
87  if (!sw.write(record.getRequest())) {
88  throw new OFInstallException(dpId, record.getRequest());
89  }
90  }
91 
92  return affectedSwitches;
93  }
94 
95  private void writeBarriers(Map<DatapathId, IOFSwitch> affectedSwitches) throws OFInstallException {
96  for (Map.Entry<DatapathId, IOFSwitch> keyValue : affectedSwitches.entrySet()) {
97  DatapathId dpId = keyValue.getKey();
98  IOFSwitch sw = keyValue.getValue();
99 
100  OfPendingMessage barrierRecord = new OfPendingMessage(dpId, sw.getOFFactory().barrierRequest());
101  if (!sw.write(barrierRecord.getRequest())) {
102  throw new OFInstallException(dpId, barrierRecord.getRequest());
103  }
104  barriers.addLast(barrierRecord);
105  }
106  }
107 
108  private boolean recordResponse(List<OfPendingMessage> pending, OFMessage response) {
109  long xid = response.getXid();
110  for (OfPendingMessage record : pending) {
111  if (record.getXid() != xid) {
112  continue;
113  }
114 
115  record.setResponse(response);
116 
117  return true;
118  }
119 
120  return false;
121  }
122 
123  private void updateBarriers() {
124  boolean allDone = true;
125 
126  for (OfPendingMessage record : barriers) {
127  if (record.isPending()) {
128  allDone = false;
129  break;
130  }
131  }
132 
133  if (allDone) {
134  removePendingState();
135  complete = true;
136  }
137  }
138 
139  private void removePendingState() {
140  for (OfPendingMessage record : batch) {
141  if (record.isPending()) {
142  record.setResponse(null);
143  }
144  }
145  }
146 
147  boolean isComplete() {
148  return complete;
149  }
150 
151  boolean isErrors() {
152  return errors;
153  }
154 
155  List<OfPendingMessage> getBatch() {
156  return batch;
157  }
158 }
IOFSwitch lookupSwitch(DatapathId dpId)
net
Definition: plan-b.py:46