aboutsummaryrefslogtreecommitdiffstats
path: root/src/vpp-api/java/jvpp
diff options
context:
space:
mode:
authorMatej <matej.perina@pantheon.tech>2017-10-23 12:55:11 +0200
committerDamjan Marion <dmarion.lists@gmail.com>2017-10-30 11:06:57 +0000
commit7008da2667d2876bc58aa5ae57c4a9de48cc756b (patch)
treeb68ab5e0363733d848161279efb9f353a2e40f62 /src/vpp-api/java/jvpp
parent04b68bdc481f21f864da63dfe36b2f05b64714a8 (diff)
jvpp: bugfix for deadlock in java future API (VPP-1037)
- message sending method inside synchronization blocks causes deadlock between sending and receiving part - breaking atomicity of sending message and putting future with corresponding id to map needs additional handling by writer and receiver, regardless which part get access to sync block first will create new future and second one will complete it and remove from map, in case of dump calls where control ping reply is required as confirmation that all information were send, if ping reply is received before writer put future in map, reader will create regular control ping future instead and writer needs to made association between these two futures Change-Id: Id29a19be7a5319291a5e07cf931080610178f00c Signed-off-by: Matej <matej.perina@pantheon.tech>
Diffstat (limited to 'src/vpp-api/java/jvpp')
-rw-r--r--src/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py60
1 files changed, 38 insertions, 22 deletions
diff --git a/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py b/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py
index a31287b3333..a45a532d7f2 100644
--- a/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py
+++ b/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_future_facade_gen.py
@@ -61,26 +61,28 @@ public final class FutureJVpp${plugin_name}FacadeCallback implements $plugin_pac
@Override
@SuppressWarnings("unchecked")
public void onControlPingReply(final $base_package.$dto_package.ControlPingReply reply) {
- final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture;
+ java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture;
final int replyId = reply.context;
synchronized(requests) {
completableFuture = (java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>>) requests.get(replyId);
- }
- if(completableFuture != null) {
- // Finish dump call
- if (completableFuture instanceof $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) {
- completableFuture.complete((($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getReplyDump());
- // Remove future mapped to dump call context id
- synchronized(requests) {
+ if(completableFuture != null) {
+ // Finish dump call
+ if (completableFuture instanceof $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) {
+ completableFuture.complete((($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getReplyDump());
+ // Remove future mapped to dump call context id
requests.remove((($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture) completableFuture).getContextId());
+ } else {
+ // reply to regular control ping, complete the future
+ completableFuture.complete(reply);
}
+ requests.remove(replyId);
} else {
+ // future not yet created by writer, create new future, complete it and put to map under ping id
+ completableFuture = new java.util.concurrent.CompletableFuture<>();
completableFuture.complete(reply);
- }
- synchronized(requests) {
- requests.remove(replyId);
+ requests.put(replyId, completableFuture);
}
}
}
@@ -93,20 +95,26 @@ jvpp_facade_callback_method_template = Template("""
@Override
@SuppressWarnings("unchecked")
public void on$callback_dto(final $plugin_package.$dto_package.$callback_dto reply) {
- final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture;
+ java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<$plugin_package.$dto_package.$request_dto>> completableFuture;
final int replyId = reply.context;
if (LOG.isLoggable(java.util.logging.Level.FINE)) {
LOG.fine(String.format("Received $callback_dto event message: %s", reply));
}
synchronized(requests) {
- completableFuture = (java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>>) requests.get(replyId);
- }
+ completableFuture =
+ (java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<$plugin_package.$dto_package.$request_dto>>) requests.get(replyId);
- if(completableFuture != null) {
- completableFuture.complete(reply);
-
- synchronized(requests) {
+ if(completableFuture != null) {
+ // received reply on request, complete future created by sender and remove it from map
+ completableFuture.complete(reply);
requests.remove(replyId);
+ } else {
+ // reply received before writer created future,
+ // create new future, complete it and put into map to
+ // notify sender that reply is already received
+ completableFuture = new java.util.concurrent.CompletableFuture<>();
+ completableFuture.complete(reply);
+ requests.put(replyId, completableFuture);
}
}
}
@@ -126,16 +134,22 @@ jvpp_facade_details_callback_method_template = Template("""
@Override
@SuppressWarnings("unchecked")
public void on$callback_dto(final $plugin_package.$dto_package.$callback_dto reply) {
- final $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.$dto_package.$callback_dto_reply_dump> completableFuture;
+ $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.$dto_package.$callback_dto_reply_dump> completableFuture;
final int replyId = reply.context;
if (LOG.isLoggable(java.util.logging.Level.FINE)) {
LOG.fine(String.format("Received $callback_dto event message: %s", reply));
}
synchronized(requests) {
completableFuture = ($base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture<$plugin_package.$dto_package.$callback_dto_reply_dump>) requests.get(replyId);
- }
- if(completableFuture != null) {
+ 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 $base_package.$future_package.AbstractFutureJVppInvoker.CompletableDumpFuture<>(replyId,
+ new $plugin_package.$dto_package.$callback_dto_reply_dump());
+ requests.put(replyId, completableFuture);
+ }
completableFuture.getReplyDump().$callback_dto_field.add(reply);
}
}
@@ -165,6 +179,7 @@ def generate_jvpp(func_list, base_package, plugin_package, plugin_name, dto_pack
if not util.is_notification(func["name"]):
camel_case_request_method_name = util.remove_reply_suffix(util.underscore_to_camelcase(func['name']))
+ request_dto = util.remove_reply_suffix(util.underscore_to_camelcase_upper(func['name']))
if util.is_details(camel_case_name_with_suffix):
camel_case_reply_name = get_standard_dump_reply_name(util.underscore_to_camelcase_upper(func['name']),
func['name'])
@@ -208,7 +223,8 @@ def generate_jvpp(func_list, base_package, plugin_package, plugin_name, dto_pack
callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package,
plugin_package=plugin_package,
dto_package=dto_package,
- callback_dto=camel_case_name_with_suffix))
+ callback_dto=camel_case_name_with_suffix,
+ request_dto=request_dto))
if util.is_notification(func["name"]):
callbacks.append(jvpp_facade_callback_notification_method_template.substitute(plugin_package=plugin_package,