diff mbox series

[ovs-dev,v3,4/5] json: Add yielding json create/destroy functions.

Message ID 20240116225205.38112-5-frode.nordahl@canonical.com
State Accepted
Commit 36bad31829016556a4cbaf36e5831866d59de84e
Delegated to: Ilya Maximets
Headers show
Series Introduce cooperative multitasking to improve OVSDB RAFT cluster operation. | expand

Checks

Context Check Description
ovsrobot/intel-ovs-compilation fail test: fail
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Frode Nordahl Jan. 16, 2024, 10:52 p.m. UTC
Creating and destroying JSON objects may be time consuming.

Add json_serialized_object_create_with_yield() and
json_destroy_with_yield() functions that make use of the
cooperative multitasking module to yield during processing,
allowing time sensitive tasks in other parts of the program
to be completed during processing.

We keep these new functions private to OVS by adding a new
lib/json.h header file.

The include guard in the public include/openvswitch/json.h is
updated to contain the OPENVSWITCH prefix to be in line with the
other public header files, allowing us to use the non-prefixed
version in our private lib/json.h.

Signed-off-by: Frode Nordahl <frode.nordahl@canonical.com>
---
 include/openvswitch/json.h | 10 +++----
 lib/automake.mk            |  1 +
 lib/json.c                 | 58 ++++++++++++++++++++++++++++++++------
 lib/json.h                 | 32 +++++++++++++++++++++
 4 files changed, 87 insertions(+), 14 deletions(-)
 create mode 100644 lib/json.h
diff mbox series

Patch

diff --git a/include/openvswitch/json.h b/include/openvswitch/json.h
index eb92c6a91..555440760 100644
--- a/include/openvswitch/json.h
+++ b/include/openvswitch/json.h
@@ -14,8 +14,8 @@ 
  * limitations under the License.
  */
 
-#ifndef JSON_H
-#define JSON_H 1
+#ifndef OPENVSWITCH_JSON_H
+#define OPENVSWITCH_JSON_H 1
 
 /* This is an implementation of JavaScript Object Notation (JSON) as specified
  * by RFC 4627.  It is intended to fully comply with RFC 4627, with the
@@ -159,14 +159,14 @@  json_clone(const struct json *json_)
     return json;
 }
 
-void json_destroy__(struct json *json);
+void json_destroy__(struct json *json, bool);
 
 /* Frees 'json' and everything it points to, recursively. */
 static inline void
 json_destroy(struct json *json)
 {
     if (json && !--json->count) {
-        json_destroy__(json);
+        json_destroy__(json, false);
     }
 }
 
@@ -174,4 +174,4 @@  json_destroy(struct json *json)
 }
 #endif
 
-#endif /* json.h */
+#endif /* OPENVSWITCH_JSON_H */
diff --git a/lib/automake.mk b/lib/automake.mk
index 8596171c6..78d6e6516 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -178,6 +178,7 @@  lib_libopenvswitch_la_SOURCES = \
 	lib/jhash.c \
 	lib/jhash.h \
 	lib/json.c \
+	lib/json.h \
 	lib/jsonrpc.c \
 	lib/jsonrpc.h \
 	lib/lacp.c \
diff --git a/lib/json.c b/lib/json.c
index 9411eeda7..001f6e6ab 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -24,13 +24,21 @@ 
 #include <limits.h>
 #include <string.h>
 
+#include "cooperative-multitasking.h"
 #include "openvswitch/dynamic-string.h"
 #include "hash.h"
+#include "json.h"
 #include "openvswitch/shash.h"
 #include "unicode.h"
 #include "util.h"
 #include "uuid.h"
 
+/* Non-public JSSF_* flags.  Must not overlap with public ones defined
+ * in include/openvswitch/json.h. */
+enum {
+    JSSF_YIELD = 1 << 7,
+};
+
 /* The type of a JSON token. */
 enum json_token_type {
     T_EOF = 0,
@@ -189,6 +197,14 @@  json_serialized_object_create(const struct json *src)
     return json;
 }
 
+struct json *
+json_serialized_object_create_with_yield(const struct json *src)
+{
+    struct json *json = json_create(JSON_SERIALIZED_OBJECT);
+    json->string = json_to_string(src, JSSF_SORT | JSSF_YIELD);
+    return json;
+}
+
 struct json *
 json_array_create_empty(void)
 {
@@ -375,20 +391,20 @@  json_integer(const struct json *json)
     return json->integer;
 }
 
-static void json_destroy_object(struct shash *object);
-static void json_destroy_array(struct json_array *array);
+static void json_destroy_object(struct shash *object, bool yield);
+static void json_destroy_array(struct json_array *array, bool yield);
 
 /* Frees 'json' and everything it points to, recursively. */
 void
-json_destroy__(struct json *json)
+json_destroy__(struct json *json, bool yield)
 {
     switch (json->type) {
     case JSON_OBJECT:
-        json_destroy_object(json->object);
+        json_destroy_object(json->object, yield);
         break;
 
     case JSON_ARRAY:
-        json_destroy_array(&json->array);
+        json_destroy_array(&json->array, yield);
         break;
 
     case JSON_STRING:
@@ -410,14 +426,22 @@  json_destroy__(struct json *json)
 }
 
 static void
-json_destroy_object(struct shash *object)
+json_destroy_object(struct shash *object, bool yield)
 {
     struct shash_node *node;
 
+    if (yield) {
+        cooperative_multitasking_yield();
+    }
+
     SHASH_FOR_EACH_SAFE (node, object) {
         struct json *value = node->data;
 
-        json_destroy(value);
+        if (yield) {
+            json_destroy_with_yield(value);
+        } else {
+            json_destroy(value);
+        }
         shash_delete(object, node);
     }
     shash_destroy(object);
@@ -425,12 +449,20 @@  json_destroy_object(struct shash *object)
 }
 
 static void
-json_destroy_array(struct json_array *array)
+json_destroy_array(struct json_array *array, bool yield)
 {
     size_t i;
 
+    if (yield) {
+        cooperative_multitasking_yield();
+    }
+
     for (i = 0; i < array->n; i++) {
-        json_destroy(array->elems[i]);
+        if (yield) {
+            json_destroy_with_yield(array->elems[i]);
+        } else {
+            json_destroy(array->elems[i]);
+        }
     }
     free(array->elems);
 }
@@ -1664,6 +1696,10 @@  json_serialize_object(const struct shash *object, struct json_serializer *s)
     s->depth++;
     indent_line(s);
 
+    if (s->flags & JSSF_YIELD) {
+        cooperative_multitasking_yield();
+    }
+
     if (s->flags & JSSF_SORT) {
         const struct shash_node **nodes;
         size_t n, i;
@@ -1697,6 +1733,10 @@  json_serialize_array(const struct json_array *array, struct json_serializer *s)
     ds_put_char(ds, '[');
     s->depth++;
 
+    if (s->flags & JSSF_YIELD) {
+        cooperative_multitasking_yield();
+    }
+
     if (array->n > 0) {
         indent_line(s);
 
diff --git a/lib/json.h b/lib/json.h
new file mode 100644
index 000000000..4ad440b39
--- /dev/null
+++ b/lib/json.h
@@ -0,0 +1,32 @@ 
+/*
+ * Copyright (c) 2024 Canonical Ltd.
+ *
+ * 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.
+ */
+
+#ifndef JSON_H
+#define JSON_H 1
+
+#include "openvswitch/json.h"
+
+static inline void
+json_destroy_with_yield(struct json *json)
+{
+    if (json && !--json->count) {
+        json_destroy__(json, true);
+    }
+}
+
+struct json *json_serialized_object_create_with_yield(const struct json *);
+
+#endif /* JSON_H */