blob: 5e577977fe20c81655ad09cd32babdb87e768216 [file] [log] [blame]
/*
* Copyright 2019-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.p4runtime.ctl.client;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.protobuf.TextFormat;
import org.onosproject.net.DeviceId;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.runtime.PiEntity;
import org.onosproject.p4runtime.api.P4RuntimeReadClient;
import org.onosproject.p4runtime.ctl.codec.CodecException;
import org.slf4j.Logger;
import p4.v1.P4RuntimeOuterClass;
import java.util.Collection;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.p4runtime.ctl.codec.Codecs.CODECS;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Handles creation of ReadResponse by parsing Read RPC server responses.
*/
public final class ReadResponseImpl implements P4RuntimeReadClient.ReadResponse {
private static final Logger log = getLogger(ReadResponseImpl.class);
public static final ReadResponseImpl EMPTY = new ReadResponseImpl(
true, ImmutableList.of(), ImmutableListMultimap.of(), null, null);
private final boolean success;
private final ImmutableList<PiEntity> entities;
private final ImmutableListMultimap<Class<? extends PiEntity>, PiEntity> typeToEntities;
private final String explanation;
private final Throwable throwable;
private ReadResponseImpl(
boolean success, ImmutableList<PiEntity> entities,
ImmutableListMultimap<Class<? extends PiEntity>, PiEntity> typeToEntities,
String explanation, Throwable throwable) {
this.success = success;
this.entities = entities;
this.typeToEntities = typeToEntities;
this.explanation = explanation;
this.throwable = throwable;
}
@Override
public boolean isSuccess() {
return success;
}
@Override
public Collection<PiEntity> all() {
return entities;
}
@Override
@SuppressWarnings("unchecked")
public <E extends PiEntity> Collection<E> all(Class<E> clazz) {
return (ImmutableList<E>) typeToEntities.get(clazz);
}
@Override
public String explanation() {
return explanation;
}
@Override
public Throwable throwable() {
return throwable;
}
static Builder builder(DeviceId deviceId, PiPipeconf pipeconf) {
return new Builder(deviceId, pipeconf);
}
/**
* Builder of P4RuntimeReadResponseImpl.
*/
static final class Builder {
private final DeviceId deviceId;
private final PiPipeconf pipeconf;
private final List<PiEntity> entities = Lists.newArrayList();
private final ListMultimap<Class<? extends PiEntity>, PiEntity>
typeToEntities = ArrayListMultimap.create();
private boolean success = true;
private String explanation;
private Throwable throwable;
private Builder(DeviceId deviceId, PiPipeconf pipeconf) {
this.deviceId = deviceId;
this.pipeconf = pipeconf;
}
void addEntity(P4RuntimeOuterClass.Entity entityMsg) {
try {
final PiEntity piEntity = CODECS.entity().decode(entityMsg, null, pipeconf);
entities.add(piEntity);
typeToEntities.put(piEntity.getClass(), piEntity);
} catch (CodecException e) {
log.warn("Unable to decode {} message from {}: {} [{}]",
entityMsg.getEntityCase().name(), deviceId,
e.getMessage(), TextFormat.shortDebugString(entityMsg));
}
}
ReadResponseImpl fail(Throwable throwable) {
checkNotNull(throwable);
this.success = false;
this.explanation = throwable.getMessage();
this.throwable = throwable;
return build();
}
ReadResponseImpl build() {
if (success && entities.isEmpty()) {
return EMPTY;
}
return new ReadResponseImpl(
success, ImmutableList.copyOf(entities),
ImmutableListMultimap.copyOf(typeToEntities),
explanation, throwable);
}
}
}