@@ -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 */
@@ -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 \
@@ -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);
new file mode 100644
@@ -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 */
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