Move java,lua api and remaining plugins to src/
[vpp.git] / src / vpp-api / java / jvpp-registry / io / fd / vpp / jvpp / VppJNIConnection.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 io.fd.vpp.jvpp.NativeLibraryLoader.loadLibrary;
20
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Objects;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 /**
29  * JNI based representation of a management connection to VPP.
30  */
31 public final class VppJNIConnection implements VppConnection {
32     private static final Logger LOG = Logger.getLogger(VppJNIConnection.class.getName());
33
34     static {
35         final String libName = "libjvpp_registry.so";
36         try {
37             loadLibrary(libName, VppJNIConnection.class);
38         } catch (IOException e) {
39             LOG.log(Level.SEVERE, String.format("Can't find vpp jni library: %s", libName), e);
40             throw new ExceptionInInitializerError(e);
41         }
42     }
43
44     private ConnectionInfo connectionInfo;
45
46     private final String clientName;
47     private volatile boolean disconnected = false;
48
49     /**
50      * Create VPPJNIConnection instance for client connecting to VPP.
51      *
52      * @param clientName client name instance to be used for communication. Single connection per clientName is
53      *                   allowed.
54      */
55     public VppJNIConnection(final String clientName) {
56         this.clientName = Objects.requireNonNull(clientName, "Null clientName");
57     }
58
59     /**
60      * Guarded by VppJNIConnection.class
61      */
62     private static final Map<String, VppJNIConnection> connections = new HashMap<>();
63
64     /**
65      * Initiate VPP connection for current instance
66      *
67      * Multiple instances are allowed since this class is not a singleton (VPP allows multiple management connections).
68      *
69      * However only a single connection per clientName is allowed.
70      *
71      * @throws IOException in case the connection could not be established
72      */
73
74     @Override
75     public void connect() throws IOException {
76         _connect();
77     }
78
79     private void _connect() throws IOException {
80         synchronized (VppJNIConnection.class) {
81             if (connections.containsKey(clientName)) {
82                 throw new IOException("Client " + clientName + " already connected");
83             }
84
85             connectionInfo = clientConnect(clientName);
86             if (connectionInfo.status != 0) {
87                 throw new IOException("Connection returned error " + connectionInfo.status);
88             }
89             connections.put(clientName, this);
90         }
91     }
92
93     @Override
94     public final void checkActive() {
95         if (disconnected) {
96             throw new IllegalStateException("Disconnected client " + clientName);
97         }
98     }
99
100     @Override
101     public final synchronized void close() {
102         if (!disconnected) {
103             disconnected = true;
104             try {
105                 clientDisconnect();
106             } finally {
107                 synchronized (VppJNIConnection.class) {
108                     connections.remove(clientName);
109                 }
110             }
111         }
112     }
113
114     public ConnectionInfo getConnectionInfo() {
115         return connectionInfo;
116     }
117
118     /**
119      * VPP connection information used by plugins to reuse the connection.
120      */
121     public static final class ConnectionInfo {
122         public final long queueAddress;
123         public final int clientIndex;
124         public final int status; // FIXME throw exception instead
125
126         public ConnectionInfo(long queueAddress, int clientIndex, int status) {
127             this.queueAddress = queueAddress;
128             this.clientIndex = clientIndex;
129             this.status = status;
130         }
131     }
132
133     private static native ConnectionInfo clientConnect(String clientName);
134
135     private static native void clientDisconnect();
136
137 }