blob: 5e577977fe20c81655ad09cd32babdb87e768216 [file] [log] [blame]
Carmelo Cascone4c289b72019-01-22 15:30:45 -08001/*
2 * Copyright 2019-present Open Networking Foundation
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
17package org.onosproject.p4runtime.ctl.client;
18
19import com.google.common.collect.ArrayListMultimap;
20import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableListMultimap;
22import com.google.common.collect.ListMultimap;
23import com.google.common.collect.Lists;
24import com.google.protobuf.TextFormat;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.pi.model.PiPipeconf;
27import org.onosproject.net.pi.runtime.PiEntity;
28import org.onosproject.p4runtime.api.P4RuntimeReadClient;
29import org.onosproject.p4runtime.ctl.codec.CodecException;
30import org.slf4j.Logger;
31import p4.v1.P4RuntimeOuterClass;
32
33import java.util.Collection;
34import java.util.List;
35
36import static com.google.common.base.Preconditions.checkNotNull;
37import static org.onosproject.p4runtime.ctl.codec.Codecs.CODECS;
38import static org.slf4j.LoggerFactory.getLogger;
39
40/**
41 * Handles creation of ReadResponse by parsing Read RPC server responses.
42 */
43public final class ReadResponseImpl implements P4RuntimeReadClient.ReadResponse {
44
45 private static final Logger log = getLogger(ReadResponseImpl.class);
46
47 public static final ReadResponseImpl EMPTY = new ReadResponseImpl(
48 true, ImmutableList.of(), ImmutableListMultimap.of(), null, null);
49
50 private final boolean success;
51 private final ImmutableList<PiEntity> entities;
52 private final ImmutableListMultimap<Class<? extends PiEntity>, PiEntity> typeToEntities;
53 private final String explanation;
54 private final Throwable throwable;
55
56 private ReadResponseImpl(
57 boolean success, ImmutableList<PiEntity> entities,
58 ImmutableListMultimap<Class<? extends PiEntity>, PiEntity> typeToEntities,
59 String explanation, Throwable throwable) {
60 this.success = success;
61 this.entities = entities;
62 this.typeToEntities = typeToEntities;
63 this.explanation = explanation;
64 this.throwable = throwable;
65 }
66
67 @Override
68 public boolean isSuccess() {
69 return success;
70 }
71
72 @Override
73 public Collection<PiEntity> all() {
74 return entities;
75 }
76
77 @Override
78 @SuppressWarnings("unchecked")
79 public <E extends PiEntity> Collection<E> all(Class<E> clazz) {
80 return (ImmutableList<E>) typeToEntities.get(clazz);
81 }
82
83 @Override
84 public String explanation() {
85 return explanation;
86 }
87
88 @Override
89 public Throwable throwable() {
90 return throwable;
91 }
92
93 static Builder builder(DeviceId deviceId, PiPipeconf pipeconf) {
94 return new Builder(deviceId, pipeconf);
95 }
96
97 /**
98 * Builder of P4RuntimeReadResponseImpl.
99 */
100 static final class Builder {
101
102 private final DeviceId deviceId;
103 private final PiPipeconf pipeconf;
104 private final List<PiEntity> entities = Lists.newArrayList();
105 private final ListMultimap<Class<? extends PiEntity>, PiEntity>
106 typeToEntities = ArrayListMultimap.create();
107
108 private boolean success = true;
109 private String explanation;
110 private Throwable throwable;
111
112 private Builder(DeviceId deviceId, PiPipeconf pipeconf) {
113 this.deviceId = deviceId;
114 this.pipeconf = pipeconf;
115 }
116
117 void addEntity(P4RuntimeOuterClass.Entity entityMsg) {
118 try {
119 final PiEntity piEntity = CODECS.entity().decode(entityMsg, null, pipeconf);
120 entities.add(piEntity);
121 typeToEntities.put(piEntity.getClass(), piEntity);
122 } catch (CodecException e) {
123 log.warn("Unable to decode {} message from {}: {} [{}]",
124 entityMsg.getEntityCase().name(), deviceId,
125 e.getMessage(), TextFormat.shortDebugString(entityMsg));
126 }
127 }
128
129 ReadResponseImpl fail(Throwable throwable) {
130 checkNotNull(throwable);
131 this.success = false;
132 this.explanation = throwable.getMessage();
133 this.throwable = throwable;
134 return build();
135 }
136
137 ReadResponseImpl build() {
138 if (success && entities.isEmpty()) {
139 return EMPTY;
140 }
141 return new ReadResponseImpl(
142 success, ImmutableList.copyOf(entities),
143 ImmutableListMultimap.copyOf(typeToEntities),
144 explanation, throwable);
145 }
146 }
147}