summaryrefslogtreecommitdiffstats
path: root/java/jvpp-stats/io/fd/jvpp
diff options
context:
space:
mode:
Diffstat (limited to 'java/jvpp-stats/io/fd/jvpp')
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/JVppClientStatsImpl.java90
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java31
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java121
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/JVppStatsRegistryImpl.java96
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/VppStatsJNIConnection.java142
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceStatisticsDetailsCallback.java25
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java23
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStats.java28
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacade.java61
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java67
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatistics.java101
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetails.java71
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetailsReplyDump.java54
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDump.java51
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/future/AbstractFutureJVppInvoker.java170
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppInvoker.java48
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java28
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java53
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java81
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiTest.java62
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/test/JvppStatsApiTest.java44
-rw-r--r--java/jvpp-stats/io/fd/jvpp/stats/test/Readme.txt9
22 files changed, 1264 insertions, 192 deletions
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/JVppClientStatsImpl.java b/java/jvpp-stats/io/fd/jvpp/stats/JVppClientStatsImpl.java
deleted file mode 100644
index 32d2345..0000000
--- a/java/jvpp-stats/io/fd/jvpp/stats/JVppClientStatsImpl.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2019 PANTHEON.tech.
- *
- * 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 io.fd.jvpp.stats;
-
-import static io.fd.jvpp.NativeLibraryLoader.loadLibrary;
-import static java.lang.String.format;
-
-import io.fd.jvpp.stats.dto.InterfaceStatistics;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-public class JVppClientStatsImpl implements AutoCloseable {
-
- private boolean connected;
-
- private static final Logger LOG = Logger.getLogger(JVppClientStatsImpl.class.getName());
-
- static {
- final String libName = "libjvpp_stats.so";
- try {
- loadLibrary(libName, JVppClientStatsImpl.class);
- } catch (IOException e) {
- LOG.log(Level.SEVERE, format("Can't find vpp jni library: %s", libName), e);
- throw new ExceptionInInitializerError(e);
- }
- }
-
- private static native InterfaceStatistics[] interfaceStatisticsDump();
- private static native int statSegmentConnect();
- private static native void statSegmentDisconnect();
-
- public synchronized List<InterfaceStatistics> getInterfaceStatistics() {
- if (!this.connected) {
- LOG.severe("Unable to dump statistics. Client isn't connected. Try reconnecting.");
- return null;
- }
- InterfaceStatistics[] statDump = interfaceStatisticsDump();
- List<InterfaceStatistics> statistics = new LinkedList();
- if (statDump != null) {
- statistics = Arrays.asList(statDump);
- }
- return statistics;
- }
-
- public JVppClientStatsImpl() {
- connectClient();
- }
-
- public boolean reconnect() {
- connectClient();
- return this.connected;
- }
-
- private void connectClient() {
- if (!this.connected) {
- if (statSegmentConnect() == 0) {
- this.connected = true;
- }
- }
- }
-
- public boolean isConnected() {
- return connected;
- }
-
- public void close() {
- if (this.connected) {
- statSegmentDisconnect();
- this.connected = false;
- }
- }
-}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java b/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java
new file mode 100644
index 0000000..c4f22dc
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats;
+
+/**
+ * <p>Java representation of plugin's api file.
+ */
+public interface JVppStats extends io.fd.jvpp.JVpp {
+ /**
+ * Generic dispatch method for sending requests to VPP
+ *
+ * @throws io.fd.jvpp.VppInvocationException if send request had failed
+ */
+ int send(io.fd.jvpp.dto.JVppRequest request) throws io.fd.jvpp.VppInvocationException;
+
+ int interfaceStatisticsDump() throws io.fd.jvpp.VppInvocationException;
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java b/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java
new file mode 100644
index 0000000..fdee289
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats;
+
+import io.fd.jvpp.JVppRegistry;
+import io.fd.jvpp.VppConnection;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.callback.JVppCallback;
+import io.fd.jvpp.dto.ControlPing;
+import io.fd.jvpp.dto.JVppRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.Set;
+import java.util.logging.Logger;
+
+public class JVppStatsImpl implements io.fd.jvpp.stats.JVppStats {
+
+ private final static Logger LOG = Logger.getLogger(JVppStatsImpl.class.getName());
+ private static final java.lang.String LIBNAME = "libjvpp_stats.so";
+
+ static {
+ try {
+ loadLibrary();
+ } catch (Exception e) {
+ LOG.severe("Can't find jvpp jni library: " + LIBNAME);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private VppConnection connection;
+ private JVppRegistry registry;
+
+ private static void loadStream(final InputStream is) throws IOException {
+ final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
+ final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms));
+ try {
+ Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+
+ try {
+ Runtime.getRuntime().load(p.toString());
+ } catch (UnsatisfiedLinkError e) {
+ throw new IOException("Failed to load library " + p, e);
+ }
+ } finally {
+ try {
+ Files.deleteIfExists(p);
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ private static void loadLibrary() throws IOException {
+ try (final InputStream is = JVppStatsImpl.class.getResourceAsStream('/' + LIBNAME)) {
+ if (is == null) {
+ throw new IOException("Failed to open library resource " + LIBNAME);
+ }
+ loadStream(is);
+ }
+ }
+
+ private static native void init0(final JVppCallback callback, final long queueAddress, final int clientIndex);
+
+ private static native int interfaceStatisticsDump0() throws io.fd.jvpp.VppInvocationException;
+
+ private static native void close0();
+
+ @Override
+ public int send(final JVppRequest request) throws VppInvocationException {
+ return request.send(this);
+ }
+
+ @Override
+ public void init(final JVppRegistry registry, final JVppCallback callback, final long queueAddress,
+ final int clientIndex) {
+ this.registry = java.util.Objects.requireNonNull(registry, "registry should not be null");
+ this.connection = java.util.Objects.requireNonNull(registry.getConnection(), "connection should not be null");
+ connection.checkActive();
+ init0(callback, queueAddress, clientIndex);
+ }
+
+ @Override
+ public int controlPing(final ControlPing controlPing) {
+ return 1;
+ }
+
+ @Override
+ public int interfaceStatisticsDump() throws VppInvocationException {
+ connection.checkActive();
+ LOG.fine("Sending interfaceStatisticsDump event message");
+ int result = interfaceStatisticsDump0();
+ if (result < 0) {
+ throw new io.fd.jvpp.VppInvocationException("interfaceStatisticsDump", result);
+ }
+ return result;
+ }
+
+ @Override
+ public void close() {
+ close0();
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsRegistryImpl.java b/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsRegistryImpl.java
new file mode 100644
index 0000000..a94a77f
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsRegistryImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats;
+
+import io.fd.jvpp.JVpp;
+import io.fd.jvpp.JVppRegistry;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.callback.JVppCallback;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Stats implementation of JVppRegistry.
+ */
+public final class JVppStatsRegistryImpl implements JVppRegistry {
+
+ private final VppStatsJNIConnection connection;
+ // Unguarded concurrent map, no race conditions expected on top of that
+ private final Map<String, JVppCallback> pluginRegistry;
+
+ public JVppStatsRegistryImpl(final String clientName) throws IOException {
+ connection = new VppStatsJNIConnection(clientName);
+ connection.connect();
+ pluginRegistry = new ConcurrentHashMap<>();
+ }
+
+ @Override
+ public VppStatsJNIConnection getConnection() {
+ return connection;
+ }
+
+ @Override
+ public void register(final JVpp jvpp, final JVppCallback callback) {
+ requireNonNull(jvpp, "jvpp should not be null");
+ requireNonNull(callback, "Callback should not be null");
+ final String name = jvpp.getClass().getName();
+ if (pluginRegistry.containsKey(name)) {
+ throw new IllegalArgumentException(
+ String.format("Callback for plugin %s was already registered", name));
+ }
+ jvpp.init(this, callback, connection.getStatsConnectionInfo().queueAddress,
+ connection.getStatsConnectionInfo().clientIndex);
+ pluginRegistry.put(name, callback);
+ }
+
+ @Override
+ public void unregister(final String name) {
+ requireNonNull(name, "Plugin name should not be null");
+ final JVppCallback previous = pluginRegistry.remove(name);
+ assertPluginWasRegistered(name, previous);
+ }
+
+ @Override
+ public JVppCallback get(final String name) {
+ requireNonNull(name, "Plugin name should not be null");
+ JVppCallback value = pluginRegistry.get(name);
+ assertPluginWasRegistered(name, value);
+ return value;
+ }
+
+ private native int controlPing0() throws VppInvocationException;
+
+ @Override
+ public int controlPing(Class<? extends JVpp> clazz) throws VppInvocationException {
+ return controlPing0();
+ }
+
+ private static void assertPluginWasRegistered(final String name, final JVppCallback value) {
+ if (value == null) {
+ throw new IllegalArgumentException(String.format("Callback for plugin %s is not registered", name));
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ connection.close();
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/VppStatsJNIConnection.java b/java/jvpp-stats/io/fd/jvpp/stats/VppStatsJNIConnection.java
new file mode 100644
index 0000000..164a553
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/VppStatsJNIConnection.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats;
+
+import io.fd.jvpp.VppConnection;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static io.fd.jvpp.NativeLibraryLoader.loadLibrary;
+import static java.lang.String.format;
+
+/**
+ * JNI based representation of a management connection to VPP.
+ */
+public final class VppStatsJNIConnection implements VppConnection {
+ private static final Logger LOG = Logger.getLogger(VppStatsJNIConnection.class.getName());
+
+ private StatsConnectionInfo connectionInfo;
+
+ private final String clientName;
+ private volatile boolean disconnected = false;
+
+ static {
+ final String libName = "libjvpp_stats_registry.so";
+ try {
+ loadLibrary(libName, VppStatsJNIConnection.class);
+ } catch (IOException e) {
+ LOG.log(Level.SEVERE, format("Can't find vpp jni library: %s", libName), e);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /**
+ * Create VPPStatsJNIConnection instance for client connecting to VPP.
+ *
+ * @param clientName client name instance to be used for communication. Single connection per clientName is
+ * allowed.
+ */
+ public VppStatsJNIConnection(final String clientName) {
+ this.clientName = Objects.requireNonNull(clientName, "Null clientName");
+ }
+
+ /**
+ * Guarded by VppStatsJNIConnection.class
+ */
+ private static final Map<String, VppStatsJNIConnection> connections = new HashMap<>();
+
+ /**
+ * Initiate VPP connection for current instance
+ * <p>
+ * Multiple instances are allowed since this class is not a singleton (VPP allows multiple management connections).
+ * <p>
+ * However only a single connection per clientName is allowed.
+ *
+ * @throws IOException in case the connection could not be established
+ */
+
+ @Override
+ public void connect() throws IOException {
+ _connect();
+ }
+
+ private void _connect() throws IOException {
+
+ synchronized (VppStatsJNIConnection.class) {
+ if (connections.containsKey(clientName)) {
+ throw new IOException("Client " + clientName + " already connected");
+ }
+
+ connectionInfo = statsConnect(clientName);
+ if (connectionInfo.status != 0) {
+ throw new IOException("Connection returned error " + connectionInfo.status);
+ }
+ connections.put(clientName, this);
+ }
+ }
+
+ @Override
+ public final void checkActive() {
+ if (disconnected) {
+ throw new IllegalStateException("Disconnected client " + clientName);
+ }
+ }
+
+ @Override
+ public final synchronized void close() {
+ if (!disconnected) {
+ disconnected = true;
+ try {
+ statsDisconnect();
+ } finally {
+ synchronized (VppStatsJNIConnection.class) {
+ connections.remove(clientName);
+ }
+ }
+ }
+ }
+
+ public StatsConnectionInfo getStatsConnectionInfo() {
+ return connectionInfo;
+ }
+
+ /**
+ * VPP connection information used by plugins to reuse the connection.
+ */
+ public static final class StatsConnectionInfo {
+ public final long queueAddress;
+ public final int clientIndex;
+ public final int status; // FIXME throw exception instead
+ public final int pid;
+
+ public StatsConnectionInfo(long queueAddress, int clientIndex, int status, int pid) {
+ this.queueAddress = queueAddress;
+ this.clientIndex = clientIndex;
+ this.status = status;
+ this.pid = pid;
+ }
+ }
+
+ private static native StatsConnectionInfo statsConnect(String clientName);
+
+ private static native void statsDisconnect();
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceStatisticsDetailsCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceStatisticsDetailsCallback.java
new file mode 100644
index 0000000..86fe189
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceStatisticsDetailsCallback.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.callback;
+
+/**
+ * <p>Represents callback for plugin's api message.
+ */
+public interface InterfaceStatisticsDetailsCallback extends io.fd.jvpp.callback.JVppCallback {
+
+ void onInterfaceStatisticsDetails(io.fd.jvpp.stats.dto.InterfaceStatisticsDetails reply);
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java
new file mode 100644
index 0000000..794a645
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.callback;
+
+/**
+ * Global aggregated callback interface.
+ */
+public interface JVppStatsGlobalCallback extends io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback {
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStats.java b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStats.java
new file mode 100644
index 0000000..307e24d
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStats.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.callfacade;
+
+import io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback;
+
+/**
+ * <p>Callback Java API representation of io.fd.jvpp.stats plugin.
+ */
+public interface CallbackJVppStats extends io.fd.jvpp.notification.EventRegistryProvider, AutoCloseable {
+
+ // TODO add send
+ void interfaceStatisticsDump(InterfaceStatisticsDetailsCallback callback) throws io.fd.jvpp.VppInvocationException;
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacade.java b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacade.java
new file mode 100644
index 0000000..f936dc1
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacade.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.callfacade;
+
+import io.fd.jvpp.notification.EventRegistry;
+
+/**
+ * <p>Default implementation of CallbackStatsJVpp interface.
+ */
+public final class CallbackJVppStatsFacade implements CallbackJVppStats {
+
+ private final io.fd.jvpp.stats.JVppStats jvpp;
+ private final java.util.Map<Integer, io.fd.jvpp.callback.JVppCallback> callbacks;
+
+ /**
+ * <p>Create CallbackJVppStatsFacade object for provided JVpp instance.
+ * Constructor internally creates CallbackJVppFacadeCallback class for processing callbacks
+ * and then connects to provided JVpp instance
+ *
+ * @param jvpp provided io.fd.jvpp.JVpp instance
+ * @throws java.io.IOException in case instance cannot connect to JVPP
+ */
+ public CallbackJVppStatsFacade(final io.fd.jvpp.JVppRegistry registry, final io.fd.jvpp.stats.JVppStats jvpp)
+ throws java.io.IOException {
+ this.jvpp = java.util.Objects.requireNonNull(jvpp, "jvpp is null");
+ this.callbacks = new java.util.HashMap<>();
+ java.util.Objects.requireNonNull(registry, "JVppRegistry should not be null");
+ registry.register(jvpp, new CallbackJVppStatsFacadeCallback(this.callbacks));
+ }
+
+ @Override
+ public void close() throws Exception {
+ jvpp.close();
+ }
+
+ public final void interfaceStatisticsDump(io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback callback)
+ throws io.fd.jvpp.VppInvocationException {
+ synchronized (callbacks) {
+ callbacks.put(jvpp.interfaceStatisticsDump(), callback);
+ }
+ }
+
+ @Override
+ public EventRegistry getEventRegistry() {
+ return null;
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java
new file mode 100644
index 0000000..ec1feb2
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.callfacade;
+
+/**
+ * <p>Implementation of JVppGlobalCallback interface for Java Callback API.
+ */
+public final class CallbackJVppStatsFacadeCallback implements io.fd.jvpp.stats.callback.JVppStatsGlobalCallback {
+
+ private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(
+ CallbackJVppStatsFacadeCallback.class.getName());
+ private final java.util.Map<Integer, io.fd.jvpp.callback.JVppCallback> requests;
+
+ public CallbackJVppStatsFacadeCallback(final java.util.Map<Integer, io.fd.jvpp.callback.JVppCallback> requestMap) {
+ this.requests = requestMap;
+ }
+
+ @Override
+ public void onError(io.fd.jvpp.VppCallbackException reply) {
+
+ io.fd.jvpp.callback.JVppCallback failedCall;
+ synchronized (requests) {
+ failedCall = requests.remove(reply.getCtxId());
+ }
+
+ if (failedCall != null) {
+ try {
+ failedCall.onError(reply);
+ } catch (RuntimeException ex) {
+ ex.addSuppressed(reply);
+ LOG.log(java.util.logging.Level.WARNING,
+ String.format("Callback: %s failed while handling exception: %s", failedCall, reply), ex);
+ }
+ }
+ }
+
+ @Override
+ public void onInterfaceStatisticsDetails(final io.fd.jvpp.stats.dto.InterfaceStatisticsDetails reply) {
+
+ io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback callback;
+ final int replyId = reply.context;
+ if (LOG.isLoggable(java.util.logging.Level.FINE)) {
+ LOG.fine(String.format("Received InterfaceStatisticsDetails event message: %s", reply));
+ }
+ synchronized (requests) {
+ callback = (io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback) requests.remove(replyId);
+ }
+
+ if (callback != null) {
+ callback.onInterfaceStatisticsDetails(reply);
+ }
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatistics.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatistics.java
index 49486a1..e831e35 100644
--- a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatistics.java
+++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatistics.java
@@ -16,25 +16,27 @@
package io.fd.jvpp.stats.dto;
+import java.util.Objects;
+
public class InterfaceStatistics {
- private int swIfIndex;
- private int outErrors;
- private int outMulticastPkts;
- private int outUnicastPkts;
- private int outBroadcastPkts;
- private int outBytes;
- private int inErrors;
- private int inMulticastPkts;
- private int inUnicastPkts;
- private int inBroadcastPkts;
- private int inBytes;
+ public int swIfIndex;
+ public int outErrors;
+ public int outMulticastPkts;
+ public int outUnicastPkts;
+ public int outBroadcastPkts;
+ public int outBytes;
+ public int inErrors;
+ public int inMulticastPkts;
+ public int inUnicastPkts;
+ public int inBroadcastPkts;
+ public int inBytes;
public InterfaceStatistics(final int swIfIndex, final int outErrors, final int outMulticastPkts,
- final int outUnicastPkts,
- final int outBroadcastPkts, final int outBytes, final int inErrors,
- final int inMulticastPkts, final int inUnicastPkts,
- final int inBroadcastPkts, final int inBytes) {
+ final int outUnicastPkts, final int outBroadcastPkts,
+ final int outBytes, final int inErrors, final int inMulticastPkts,
+ final int inUnicastPkts, final int inBroadcastPkts,
+ final int inBytes) {
this.swIfIndex = swIfIndex;
this.outErrors = outErrors;
this.outMulticastPkts = outMulticastPkts;
@@ -48,52 +50,37 @@ public class InterfaceStatistics {
this.inBytes = inBytes;
}
- public int getSwIfIndex() {
- return swIfIndex;
- }
-
- public int getOutErrors() {
- return outErrors;
- }
-
- public int getOutMulticastPkts() {
- return outMulticastPkts;
- }
-
- public int getOutUnicastPkts() {
- return outUnicastPkts;
- }
-
- public int getOutBroadcastPkts() {
- return outBroadcastPkts;
- }
-
- public int getOutBytes() {
- return outBytes;
- }
-
- public int getInErrors() {
- return inErrors;
- }
-
- public int getInMulticastPkts() {
- return inMulticastPkts;
- }
-
- public int getInUnicastPkts() {
- return inUnicastPkts;
- }
-
- public int getInBroadcastPkts() {
- return inBroadcastPkts;
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+ final InterfaceStatistics otherIfcStats = (InterfaceStatistics) other;
+ return swIfIndex == otherIfcStats.swIfIndex &&
+ outErrors == otherIfcStats.outErrors &&
+ outMulticastPkts == otherIfcStats.outMulticastPkts &&
+ outUnicastPkts == otherIfcStats.outUnicastPkts &&
+ outBroadcastPkts == otherIfcStats.outBroadcastPkts &&
+ outBytes == otherIfcStats.outBytes &&
+ inErrors == otherIfcStats.inErrors &&
+ inMulticastPkts == otherIfcStats.inMulticastPkts &&
+ inUnicastPkts == otherIfcStats.inUnicastPkts &&
+ inBroadcastPkts == otherIfcStats.inBroadcastPkts &&
+ inBytes == otherIfcStats.inBytes;
}
- public int getInBytes() {
- return inBytes;
+ @Override
+ public int hashCode() {
+ return Objects
+ .hash(swIfIndex, outErrors, outMulticastPkts, outUnicastPkts, outBroadcastPkts, outBytes, inErrors,
+ inMulticastPkts, inUnicastPkts, inBroadcastPkts, inBytes);
}
- @java.lang.Override
- public java.lang.String toString() {
+ @Override
+ public String toString() {
return "InterfaceStatistics{" +
"swIfIndex=" + swIfIndex +
", outErrors=" + outErrors +
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetails.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetails.java
new file mode 100644
index 0000000..997dc70
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetails.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.dto;
+
+/**
+ * <p>This class represents reply DTO for InterfaceStatisticsDetails.
+ */
+public final class InterfaceStatisticsDetails implements io.fd.jvpp.dto.JVppReply<InterfaceStatisticsDump> {
+ public int context;
+ public InterfaceStatistics[] interfaceStatistics;
+ public int length;
+
+ public InterfaceStatisticsDetails(int length, int context) {
+ this.context = context;
+ this.length = length;
+ this.interfaceStatistics = new InterfaceStatistics[length];
+ }
+
+ @Override
+ @io.fd.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD")
+ public int hashCode() {
+ return java.util.Objects.hash(context, interfaceStatistics, length);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final InterfaceStatisticsDetails other = (InterfaceStatisticsDetails) o;
+
+ if (!java.util.Objects.equals(this.context, other.context)) {
+ return false;
+ }
+ if (!java.util.Arrays.equals(this.interfaceStatistics, other.interfaceStatistics)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.length, other.length)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public java.lang.String toString() {
+ return "InterfaceStatisticsDetails{" +
+ "context=" + context +
+ ", interfaceStatistics=" + java.util.Arrays.toString(interfaceStatistics) +
+ ", length=" + length +
+ '}';
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetailsReplyDump.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetailsReplyDump.java
new file mode 100644
index 0000000..53ef30f
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDetailsReplyDump.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.dto;
+
+/**
+ * <p>This class represents dump reply wrapper for InterfaceStatisticsDetails.
+ */
+public final class InterfaceStatisticsDetailsReplyDump
+ implements io.fd.jvpp.dto.JVppReplyDump<InterfaceStatisticsDump, InterfaceStatisticsDetails> {
+
+ public InterfaceStatisticsDetails interfaceStatisticsDetails;
+
+ @Override
+ @io.fd.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD")
+ public int hashCode() {
+ return java.util.Objects.hash(interfaceStatisticsDetails);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final InterfaceStatisticsDetailsReplyDump
+ other = (InterfaceStatisticsDetailsReplyDump) o;
+
+ return java.util.Objects.equals(this.interfaceStatisticsDetails, other.interfaceStatisticsDetails);
+ }
+
+ @Override
+ public String toString() {
+ return "InterfaceStatisticsDetailsReplyDump{" +
+ "interfaceStatisticsDetails=" + interfaceStatisticsDetails +
+ '}';
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDump.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDump.java
new file mode 100644
index 0000000..e51936a
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceStatisticsDump.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.dto;
+
+/**
+ * <p>This class represents request DTO.
+ */
+public final class InterfaceStatisticsDump implements io.fd.jvpp.dto.JVppDump {
+
+ @Override
+ @io.fd.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD")
+ public int hashCode() {
+ return java.util.Objects.hash();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "InterfaceStatisticsDump{}";
+ }
+
+ @Override
+ public int send(final io.fd.jvpp.JVpp jvpp) throws io.fd.jvpp.VppInvocationException {
+ return ((io.fd.jvpp.stats.JVppStats) jvpp).interfaceStatisticsDump();
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/AbstractFutureJVppInvoker.java b/java/jvpp-stats/io/fd/jvpp/stats/future/AbstractFutureJVppInvoker.java
new file mode 100644
index 0000000..e66cfd8
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/future/AbstractFutureJVppInvoker.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.future;
+
+
+import io.fd.jvpp.JVpp;
+import io.fd.jvpp.JVppRegistry;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.dto.JVppDump;
+import io.fd.jvpp.dto.JVppReply;
+import io.fd.jvpp.dto.JVppReplyDump;
+import io.fd.jvpp.dto.JVppRequest;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+/**
+ * Future facade on top of JVpp
+ */
+public abstract class AbstractFutureJVppInvoker implements FutureJVppInvoker {
+
+ private final JVpp jvpp;
+ private final JVppRegistry registry;
+
+ /**
+ * Guarded by self
+ */
+ private final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requests;
+
+ protected AbstractFutureJVppInvoker(final JVpp jvpp, final JVppRegistry registry,
+ final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requestMap) {
+ this.jvpp = Objects.requireNonNull(jvpp, "jvpp should not be null");
+ this.registry = Objects.requireNonNull(registry, "registry should not be null");
+ // Request map represents the shared state between this facade and it's callback
+ // where facade puts futures in and callback completes + removes them
+ this.requests = Objects.requireNonNull(requestMap, "Null requestMap");
+ }
+
+ protected final Map<Integer, CompletableFuture<? extends JVppReply<?>>> getRequests() {
+ synchronized (requests) {
+ return requests;
+ }
+ }
+
+ // TODO use Optional in Future, java8
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req) {
+ try {
+ // jvpp.send() can go to waiting state if sending queue is full, putting it into same
+ // synchronization block as used by receiving part (synchronized(requests)) can lead
+ // to deadlock between these two sides or at least slowing sending process by slow
+ // reader
+ final CompletableFuture<REPLY> replyCompletableFuture;
+ final int contextId = jvpp.send(req);
+
+ if(req instanceof JVppDump) {
+ throw new IllegalArgumentException("Send with empty reply dump has to be used in case of dump calls");
+ }
+
+ synchronized(requests) {
+ CompletableFuture<? extends JVppReply<?>> replyFuture = requests.get(contextId);
+ if (replyFuture == null) {
+ // reply not yet received, put new future into map
+ replyCompletableFuture = new CompletableFuture<>();
+ requests.put(contextId, replyCompletableFuture);
+ } else {
+ // reply already received (should be completed by reader),
+ // remove future from map and return it to caller
+ replyCompletableFuture = (CompletableFuture<REPLY>) replyFuture;
+ requests.remove(contextId);
+ }
+ }
+
+ // TODO in case of timeouts/missing replies, requests from the map are not removed
+ // consider adding cancel method, that would remove requests from the map and cancel
+ // associated replyCompletableFuture
+
+ return replyCompletableFuture;
+ } catch (VppInvocationException ex) {
+ final CompletableFuture<REPLY> replyCompletableFuture = new CompletableFuture<>();
+ replyCompletableFuture.completeExceptionally(ex);
+ return replyCompletableFuture;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <REQ extends JVppRequest, REPLY extends JVppReply<REQ>, DUMP extends JVppReplyDump<REQ, REPLY>> CompletionStage<DUMP> send(
+ REQ req, DUMP emptyReplyDump) {
+ try {
+ // jvpp.send() can go to waiting state if sending queue is full,
+ // putting it into same synchronization block as used by receiving part (synchronized(requests))
+ // can lead to deadlock between these two sides or at least slowing sending process by slow reader
+ final CompletableDumpFuture<DUMP> replyDumpFuture;
+ final int contextId = jvpp.send(req);
+
+ if(!(req instanceof JVppDump)) {
+ throw new IllegalArgumentException("Send without empty reply dump has to be used in case of regular calls");
+ }
+
+ synchronized(requests) {
+ CompletableFuture<? extends JVppReply<?>> replyFuture = requests.get(contextId);
+ if (replyFuture == null) {
+ // reply not received yet, put new future to map
+ replyDumpFuture = new CompletableDumpFuture<>(contextId, emptyReplyDump);
+ requests.put(contextId, replyDumpFuture);
+ } else {
+ // reply already received, save existing future
+ replyDumpFuture = (CompletableDumpFuture<DUMP>) replyFuture;
+ }
+ }
+
+ synchronized (requests) {
+ // reply already received, complete future
+ replyDumpFuture.complete(replyDumpFuture.getReplyDump());
+ requests.remove(contextId);
+ }
+
+ // TODO in case of timeouts/missing replies, requests from the map are not removed
+ // consider adding cancel method, that would remove requests from the map and cancel
+ // associated replyCompletableFuture
+
+ return replyDumpFuture;
+ } catch (VppInvocationException ex) {
+ final CompletableFuture<DUMP> replyCompletableFuture = new CompletableFuture<>();
+ replyCompletableFuture.completeExceptionally(ex);
+ return replyCompletableFuture;
+ }
+ }
+
+ public static final class CompletableDumpFuture<T extends JVppReplyDump<?, ?>> extends CompletableFuture<T> {
+ private final T replyDump;
+ private final int contextId;
+
+ public CompletableDumpFuture(final int contextId, final T emptyDump) {
+ this.contextId = contextId;
+ this.replyDump = emptyDump;
+ }
+
+ public int getContextId() {
+ return contextId;
+ }
+
+ public T getReplyDump() {
+ return replyDump;
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ jvpp.close();
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppInvoker.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppInvoker.java
new file mode 100644
index 0000000..c93c332
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppInvoker.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.future;
+
+
+import io.fd.jvpp.dto.JVppReply;
+import io.fd.jvpp.dto.JVppReplyDump;
+import io.fd.jvpp.dto.JVppRequest;
+import io.fd.jvpp.notification.EventRegistryProvider;
+import java.util.concurrent.CompletionStage;
+
+/**
+* Future facade on top of JVpp
+*/
+public interface FutureJVppInvoker extends EventRegistryProvider, AutoCloseable {
+
+ /**
+ * Invoke asynchronous operation on VPP
+ *
+ * @return CompletionStage with future result of an async VPP call
+ * @throws io.fd.jvpp.VppInvocationException when send request failed with details
+ */
+ <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req);
+
+
+ /**
+ * Invoke asynchronous dump operation on VPP
+ *
+ * @return CompletionStage with aggregated future result of an async VPP dump call
+ * @throws io.fd.jvpp.VppInvocationException when send request failed with details
+ */
+ <REQ extends JVppRequest, REPLY extends JVppReply<REQ>, DUMP extends JVppReplyDump<REQ, REPLY>> CompletionStage<DUMP> send(
+ REQ req, DUMP emptyReplyDump);
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java
new file mode 100644
index 0000000..288b556
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.future;
+
+import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump;
+
+/**
+ * <p>Async facade extension adding specific methods for each request invocation
+ */
+public interface FutureJVppStats extends io.fd.jvpp.stats.future.FutureJVppInvoker {
+
+ java.util.concurrent.CompletionStage<InterfaceStatisticsDetailsReplyDump> interfaceStatisticsDump(
+ io.fd.jvpp.stats.dto.InterfaceStatisticsDump request);
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java
new file mode 100644
index 0000000..470a2fd
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.future;
+
+import io.fd.jvpp.notification.EventRegistry;
+import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump;
+
+/**
+ * <p>Implementation of FutureJVpp based on AbstractFutureJVppInvoker
+ */
+public class FutureJVppStatsFacade extends io.fd.jvpp.stats.future.AbstractFutureJVppInvoker
+ implements FutureJVppStats {
+
+ /**
+ * <p>Create FutureJVppStatsFacade object for provided JVpp instance.
+ * Constructor internally creates FutureJVppFacadeCallback class for processing callbacks
+ * and then connects to provided JVpp instance
+ *
+ * @param jvpp provided io.fd.jvpp.JVpp instance
+ * @throws java.io.IOException in case instance cannot connect to JVPP
+ */
+ public FutureJVppStatsFacade(final io.fd.jvpp.JVppRegistry registry, final io.fd.jvpp.JVpp jvpp)
+ throws java.io.IOException {
+ super(jvpp, registry, new java.util.HashMap<>());
+ java.util.Objects.requireNonNull(registry, "JVppRegistry should not be null");
+ registry.register(jvpp, new FutureJVppStatsFacadeCallback(getRequests()));
+ }
+
+ @Override
+ public java.util.concurrent.CompletionStage<InterfaceStatisticsDetailsReplyDump> interfaceStatisticsDump(
+ io.fd.jvpp.stats.dto.InterfaceStatisticsDump request) {
+ return send(request, new InterfaceStatisticsDetailsReplyDump());
+ }
+
+ @Override
+ public EventRegistry getEventRegistry() {
+ return null;
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java
new file mode 100644
index 0000000..a215b89
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.future;
+
+import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump;
+
+/**
+ * <p>Async facade callback setting values to future objects
+ */
+public final class FutureJVppStatsFacadeCallback implements io.fd.jvpp.stats.callback.JVppStatsGlobalCallback {
+
+ private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(
+ FutureJVppStatsFacadeCallback.class.getName());
+ private final java.util.Map<Integer, java.util.concurrent.CompletableFuture<? extends io.fd.jvpp.dto.JVppReply<?>>>
+ requests;
+
+ public FutureJVppStatsFacadeCallback(
+ final java.util.Map<Integer, java.util.concurrent.CompletableFuture<? extends io.fd.jvpp.dto.JVppReply<?>>> requestMap) {
+ this.requests = requestMap;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void onError(io.fd.jvpp.VppCallbackException reply) {
+ final java.util.concurrent.CompletableFuture<io.fd.jvpp.dto.JVppReply<?>> completableFuture;
+
+ synchronized (requests) {
+ completableFuture = (java.util.concurrent.CompletableFuture<io.fd.jvpp.dto.JVppReply<?>>) requests
+ .get(reply.getCtxId());
+ }
+
+ if (completableFuture != null) {
+ completableFuture.completeExceptionally(reply);
+
+ synchronized (requests) {
+ requests.remove(reply.getCtxId());
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void onInterfaceStatisticsDetails(final io.fd.jvpp.stats.dto.InterfaceStatisticsDetails reply) {
+ io.fd.jvpp.stats.future.AbstractFutureJVppInvoker.CompletableDumpFuture<InterfaceStatisticsDetailsReplyDump>
+ completableFuture;
+ final int replyId = reply.context;
+ if (LOG.isLoggable(java.util.logging.Level.FINE)) {
+ LOG.fine(String.format("Received InterfaceStatisticsDetails event message: %s", reply));
+ }
+ synchronized (requests) {
+ completableFuture =
+ (io.fd.jvpp.stats.future.AbstractFutureJVppInvoker.CompletableDumpFuture<InterfaceStatisticsDetailsReplyDump>) requests
+ .get(replyId);
+
+ if (completableFuture == null) {
+ // reply received before writer created future,
+ // create new future, and put into map to notify sender that reply is already received,
+ // following details replies will add information to this future
+ completableFuture =
+ new io.fd.jvpp.stats.future.AbstractFutureJVppInvoker.CompletableDumpFuture<>(replyId,
+ new InterfaceStatisticsDetailsReplyDump());
+ requests.put(replyId, completableFuture);
+ }
+ completableFuture.getReplyDump().interfaceStatisticsDetails = reply;
+ }
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiTest.java b/java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiTest.java
new file mode 100644
index 0000000..2b28915
--- /dev/null
+++ b/java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * 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 io.fd.jvpp.stats.test;
+
+
+import io.fd.jvpp.JVppRegistry;
+import io.fd.jvpp.stats.JVppStatsImpl;
+import io.fd.jvpp.stats.JVppStatsRegistryImpl;
+import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump;
+import io.fd.jvpp.stats.dto.InterfaceStatisticsDump;
+import io.fd.jvpp.stats.future.FutureJVppStatsFacade;
+import java.util.concurrent.Future;
+import java.util.logging.Logger;
+
+public class FutureApiTest {
+
+ private static final Logger LOG = Logger.getLogger(FutureApiTest.class.getName());
+
+ public static void main(String[] args) throws Exception {
+ testCallbackApi(args);
+ }
+
+ private static void testCallbackApi(String[] args) throws Exception {
+ LOG.info("Testing Java callback API for stats plugin");
+ try (final JVppRegistry registry = new JVppStatsRegistryImpl("FutureApiTest");
+ final FutureJVppStatsFacade jvpp = new FutureJVppStatsFacade(registry, new JVppStatsImpl())) {
+ LOG.info("Successfully connected to VPP");
+ testinterfaceStatisticsDump(jvpp);
+
+ LOG.info("Disconnecting...");
+ }
+ }
+
+ private static void testinterfaceStatisticsDump(FutureJVppStatsFacade jvpp) throws Exception {
+ LOG.info("Sending InterfaceStatisticsDump request...");
+ final InterfaceStatisticsDump request = new InterfaceStatisticsDump();
+
+ final Future<InterfaceStatisticsDetailsReplyDump> replyFuture =
+ jvpp.interfaceStatisticsDump(request).toCompletableFuture();
+ final InterfaceStatisticsDetailsReplyDump reply = replyFuture.get();
+
+ if (reply == null || reply.interfaceStatisticsDetails == null) {
+ throw new IllegalStateException("Received null response for empty dump: " + reply);
+ } else {
+ LOG.info(String.format("Received interface statistics reply: %s \n", reply.interfaceStatisticsDetails));
+ }
+ }
+}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/test/JvppStatsApiTest.java b/java/jvpp-stats/io/fd/jvpp/stats/test/JvppStatsApiTest.java
deleted file mode 100644
index 2f9cf9f..0000000
--- a/java/jvpp-stats/io/fd/jvpp/stats/test/JvppStatsApiTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2019 PANTHEON.tech.
- *
- * 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 io.fd.jvpp.stats.test;
-
-import io.fd.jvpp.stats.JVppClientStatsImpl;
-import io.fd.jvpp.stats.dto.InterfaceStatistics;
-import java.util.List;
-
-class JvppStatsApiTest {
-
- public static void main(String[] args) {
-
- JVppClientStatsImpl myImpl = new JVppClientStatsImpl();
- List<InterfaceStatistics> statistics = myImpl.getInterfaceStatistics();
-
- if (statistics == null) {
- System.out.println("in java - dump was null");
- System.exit(1);
- }
-
- if (statistics.size() == 0) {
- System.out.println("in java - dump was empty");
- System.exit(2);
- }
-
- for (InterfaceStatistics stat: statistics) {
- System.out.println(stat.toString());
- }
- }
-}
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/test/Readme.txt b/java/jvpp-stats/io/fd/jvpp/stats/test/Readme.txt
index cda9ed2..9fb22cc 100644
--- a/java/jvpp-stats/io/fd/jvpp/stats/test/Readme.txt
+++ b/java/jvpp-stats/io/fd/jvpp/stats/test/Readme.txt
@@ -2,4 +2,11 @@ This package contains basic tests for jvpp. To run the tests:
- Make sure VPP is running
- From JVPP's java/ folder execute:
- - sudo java -cp jvpp-registry-19.04.jar:jvpp-stats-19.04.jar io.fd.jvpp.stats.test.JvppStatsApiTest
+ - "sudo java -cp jvpp-registry-19.08.jar:jvpp-stats-19.08.jar io.fd.jvpp.stats.test.FutureApiTest"
+- For debug use:
+ - "sudo java -verbose:jni -Xcheck:jni -cp jvpp-registry-19.08.jar:jvpp-stats-19.08.jar io.fd.jvpp.stats.test.FutureApiTest"
+ - in the case there is a core dump generated use GDB for backtrace:
+ - "sudo gdb java core"
+ - then in GDB console use "bt full" command to print backtrace.
+ - if libraries are missing use "info sharedlibrary" in GDB to find out path and name of missing libraries.
+ You can copy missing libraries to desired location (usually /tmp/, because the libs are extracted from jars on startup) \ No newline at end of file