blob: 9df6a86b6163c21b8f56d64e646c21497146f5ea [file] [log] [blame]
Carmelo Cascone326ad2d2017-11-28 18:09:13 -08001/*
2 * Copyright 2017-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.store.pi.impl;
18
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.onosproject.net.pi.runtime.PiEntity;
25import org.onosproject.net.pi.runtime.PiHandle;
26import org.onosproject.net.pi.service.PiTranslatable;
27import org.onosproject.net.pi.service.PiTranslatedEntity;
28import org.onosproject.net.pi.service.PiTranslationEvent;
29import org.onosproject.net.pi.service.PiTranslationStore;
30import org.onosproject.net.pi.service.PiTranslationStoreDelegate;
31import org.onosproject.store.AbstractStore;
32import org.onosproject.store.serializers.KryoNamespaces;
33import org.onosproject.store.service.EventuallyConsistentMap;
34import org.onosproject.store.service.EventuallyConsistentMapEvent;
35import org.onosproject.store.service.EventuallyConsistentMapListener;
36import org.onosproject.store.service.StorageService;
37import org.onosproject.store.service.WallClockTimestamp;
38import org.slf4j.Logger;
39
40import static com.google.common.base.Preconditions.checkArgument;
41import static com.google.common.base.Preconditions.checkNotNull;
42import static java.lang.String.format;
43import static org.slf4j.LoggerFactory.getLogger;
44
45/**
46 * Distributed implementation of PiTranslationStore.
47 */
48@Component(immediate = true)
49public abstract class AbstractDistributedPiTranslationStore
50 <T extends PiTranslatable, E extends PiEntity>
51 extends AbstractStore<PiTranslationEvent<T, E>, PiTranslationStoreDelegate<T, E>>
52 implements PiTranslationStore<T, E> {
53
54 private static final String MAP_NAME_TEMPLATE = "onos-pi-translated-%s-map";
55
56 private final Logger log = getLogger(getClass());
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected StorageService storageService;
60
61 private EventuallyConsistentMap<PiHandle<E>, PiTranslatedEntity<T, E>>
62 translatedEntities;
63
64 private final EventuallyConsistentMapListener
65 <PiHandle<E>, PiTranslatedEntity<T, E>> entityMapListener =
66 new InternalEntityMapListener();
67
68 /**
69 * Returns a string that identifies the map maintained by this store among
70 * others that uses this abstract class.
71 *
72 * @return string
73 */
74 protected abstract String mapSimpleName();
75
76 @Activate
77 public void activate() {
78 final String fullMapName = format(MAP_NAME_TEMPLATE, mapSimpleName());
79 translatedEntities = storageService
80 .<PiHandle<E>, PiTranslatedEntity<T, E>>eventuallyConsistentMapBuilder()
81 .withName(fullMapName)
82 .withSerializer(KryoNamespaces.API)
83 .withTimestampProvider((k, v) -> new WallClockTimestamp())
84 .build();
85 translatedEntities.addListener(entityMapListener);
86 log.info("Started");
87 }
88
89 @Deactivate
90 public void deactivate() {
91 translatedEntities.removeListener(entityMapListener);
92 translatedEntities = null;
93 log.info("Stopped");
94 }
95
96 @Override
97 public void addOrUpdate(PiHandle<E> handle, PiTranslatedEntity<T, E> entity) {
98 checkNotNull(handle);
99 checkNotNull(entity);
100 checkArgument(handle.entityType().equals(entity.entityType()),
101 "Entity type must be the same for handle and translated entity");
102 translatedEntities.put(handle, entity);
103 }
104
105 @Override
106 public void remove(PiHandle<E> handle) {
107 checkNotNull(handle);
108 translatedEntities.remove(handle);
109 }
110
111 @Override
112 public PiTranslatedEntity<T, E> get(PiHandle<E> handle) {
113 checkNotNull(handle);
114 return translatedEntities.get(handle);
115 }
116
117 public Iterable<PiTranslatedEntity<T, E>> getAll() {
118 return translatedEntities.values();
119 }
120
121 private class InternalEntityMapListener
122 implements EventuallyConsistentMapListener
123 <PiHandle<E>, PiTranslatedEntity<T, E>> {
124
125 @Override
126 public void event(EventuallyConsistentMapEvent<PiHandle<E>,
127 PiTranslatedEntity<T, E>> event) {
128 final PiTranslationEvent.Type type;
129 switch (event.type()) {
130 case PUT:
131 type = PiTranslationEvent.Type.LEARNED;
132 break;
133 case REMOVE:
134 type = PiTranslationEvent.Type.FORGOT;
135 break;
136 default:
137 throw new IllegalArgumentException(
138 "Unknown event type " + event.type().name());
139 }
140 notifyDelegate(new PiTranslationEvent<>(type, event.value()));
141 }
142 }
143}