Move java,lua api and remaining plugins to src/
[vpp.git] / src / vpp-api / java / jvpp-registry / io / fd / vpp / jvpp / JVppRegistryImpl.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
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
17 package io.fd.vpp.jvpp;
18
19 import static java.util.Objects.requireNonNull;
20
21 import io.fd.vpp.jvpp.callback.ControlPingCallback;
22 import io.fd.vpp.jvpp.callback.JVppCallback;
23 import io.fd.vpp.jvpp.dto.ControlPingReply;
24 import java.io.IOException;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.logging.Level;
29 import java.util.logging.Logger;
30
31 /**
32  * Default implementation of JVppRegistry.
33  */
34 public final class JVppRegistryImpl implements JVppRegistry, ControlPingCallback {
35
36     private static final Logger LOG = Logger.getLogger(JVppRegistryImpl.class.getName());
37
38     private final VppJNIConnection connection;
39     // Unguarded concurrent map, no race conditions expected on top of that
40     private final Map<String, JVppCallback> pluginRegistry;
41     // Guarded by self
42     private final Map<Integer, ControlPingCallback> pingCalls;
43
44     public JVppRegistryImpl(final String clientName) throws IOException {
45         connection = new VppJNIConnection(clientName);
46         connection.connect();
47         pluginRegistry = new ConcurrentHashMap<>();
48         pingCalls = new HashMap<>();
49     }
50
51     @Override
52     public VppConnection getConnection() {
53         return connection;
54     }
55
56     @Override
57     public void register(final JVpp jvpp, final JVppCallback callback) {
58         requireNonNull(jvpp, "jvpp should not be null");
59         requireNonNull(callback, "Callback should not be null");
60         final String name = jvpp.getClass().getName();
61         if (pluginRegistry.containsKey(name)) {
62             throw new IllegalArgumentException(
63                 String.format("Callback for plugin %s was already registered", name));
64         }
65         jvpp.init(this, callback, connection.getConnectionInfo().queueAddress,
66             connection.getConnectionInfo().clientIndex);
67         pluginRegistry.put(name, callback);
68     }
69
70     @Override
71     public void unregister(final String name) {
72         requireNonNull(name, "Plugin name should not be null");
73         final JVppCallback previous = pluginRegistry.remove(name);
74         assertPluginWasRegistered(name, previous);
75     }
76
77     @Override
78     public JVppCallback get(final String name) {
79         requireNonNull(name, "Plugin name should not be null");
80         JVppCallback value = pluginRegistry.get(name);
81         assertPluginWasRegistered(name, value);
82         return value;
83     }
84
85     private native int controlPing0() throws VppInvocationException;
86
87     @Override
88     public int controlPing(final Class<? extends JVpp> clazz) throws VppInvocationException {
89         connection.checkActive();
90         final String name = clazz.getName();
91
92         final ControlPingCallback callback = (ControlPingCallback) pluginRegistry.get(clazz.getName());
93         assertPluginWasRegistered(name, callback);
94
95         synchronized (pingCalls) {
96             int context = controlPing0();
97             if (context < 0) {
98                 throw new VppInvocationException("controlPing", context);
99             }
100
101             pingCalls.put(context, callback);
102             return context;
103         }
104     }
105
106     @Override
107     public void onControlPingReply(final ControlPingReply reply) {
108         final ControlPingCallback callback;
109         synchronized (pingCalls) {
110             callback = pingCalls.remove(reply.context);
111             if (callback == null) {
112                 LOG.log(Level.WARNING, "No callback was registered for reply context=" + reply.context + " Contexts waiting="
113                     + pingCalls.keySet());
114                 return;
115             }
116         }
117         // pass the reply to the callback registered by the ping caller
118         callback.onControlPingReply(reply);
119     }
120
121     @Override
122     public void onError(final VppCallbackException ex) {
123         final int ctxId = ex.getCtxId();
124         final ControlPingCallback callback;
125
126         synchronized (pingCalls) {
127             callback = pingCalls.get(ctxId);
128         }
129         if (callback == null) {
130             LOG.log(Level.WARNING, "No callback was registered for reply id={0} ", ctxId);
131             return;
132         }
133         // pass the error to the callback registered by the ping caller
134         callback.onError(ex);
135     }
136
137     private static void assertPluginWasRegistered(final String name, final JVppCallback value) {
138         if (value == null) {
139             throw new IllegalArgumentException(String.format("Callback for plugin %s is not registered", name));
140         }
141     }
142
143     @Override
144     public void close() throws Exception {
145         connection.close();
146     }
147 }