[CRIU] [PATCH 1/6] protobuf: "pretty" show engine introduced

Kinsbursky Stanislav skinsbursky at openvz.org
Fri Jul 27 10:06:27 EDT 2012


The idea is simple: pass array of pointers to show engine. Non-NULL function
pointer in the array indicates, that it's the pointer to corresponding custom
show function.
If the field is a nested message, then the pointer indicates another "pretty"
array for nested message.

Signed-off-by: Stanislav Kinsbursky <skinsbursky at openvz.org>

---
 include/protobuf.h |   18 ++++++++++-
 protobuf.c         |   82 ++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 72 insertions(+), 28 deletions(-)

diff --git a/include/protobuf.h b/include/protobuf.h
index e13c3e4..f0262d5 100644
--- a/include/protobuf.h
+++ b/include/protobuf.h
@@ -24,10 +24,16 @@ typedef size_t (*pb_pack_t)(void *obj, void *where);
 typedef void  *(*pb_unpack_t)(void *allocator, size_t size, void *from);
 typedef void   (*pb_free_t)(void *obj, void *allocator);
 
+typedef void (*pb_pr_field_t)(void *obj, void *ctl);
+
 extern int pb_read_object_with_header(int fd, void **pobj,
 				      pb_unpack_t unpack,
 				      bool eof);
 
+#ifdef CONFIG_X86_64
+#define PTR_TO_PRETTY_ARRAY(ptr)	((pb_pr_field_t)(((unsigned long)ptr) + (~LONG_MAX)))
+#endif
+
 #define PB_UNPACK_TYPECHECK(__op, __fn)	({ if (0) *__op = __fn##__unpack(NULL, 0, NULL); (pb_unpack_t)&__fn##__unpack; })
 #define PB_PACK_TYPECHECK(__o, __fn)	({ if (0) __fn##__pack(__o, NULL); (pb_pack_t)&__fn##__pack; })
 #define PB_GPS_TYPECHECK(__o, __fn)	({ if (0) __fn##__get_packed_size(__o); (pb_getpksize_t)&__fn##__get_packed_size; })
@@ -61,14 +67,20 @@ extern int pb_write_object_with_header(int fd, void *obj,
 extern void do_pb_show_plain(int fd, const ProtobufCMessageDescriptor *d,
 		pb_unpack_t unpack, pb_free_t free, int single_entry,
 		void (*payload_hadler)(int fd, void *obj, int flags),
-		int flags);
+		int flags, pb_pr_field_t *pretty_array);
 
 /* Don't have objects at hands to also do typechecking here */
 #define pb_show_plain_payload(__fd, __proto_message_name, payload_hadler, flags)	\
 	do_pb_show_plain(__fd, &__proto_message_name##__descriptor,	\
 			(pb_unpack_t)__proto_message_name##__unpack,			\
 			(pb_free_t)__proto_message_name##__free_unpacked,		\
-			0, payload_hadler, flags)
+			0, payload_hadler, flags, NULL)
+
+#define pb_show_plain_pretty(__fd, __proto_message_name, pretty_array)			\
+	do_pb_show_plain(__fd, &__proto_message_name##__descriptor,	\
+			(pb_unpack_t)__proto_message_name##__unpack,			\
+			(pb_free_t)__proto_message_name##__free_unpacked,		\
+			0, NULL, 0, pretty_array)
 
 #define pb_show_plain(__fd, __proto_message_name)			\
 	pb_show_plain_payload(__fd, __proto_message_name, NULL, 0)
@@ -77,6 +89,6 @@ extern void do_pb_show_plain(int fd, const ProtobufCMessageDescriptor *d,
 	do_pb_show_plain(__fd, &__proto_message_name##__descriptor,	\
 			(pb_unpack_t)__proto_message_name##__unpack,			\
 			(pb_free_t)__proto_message_name##__free_unpacked,		\
-			1, NULL, 0)
+			1, NULL, 0, NULL)
 
 #endif /* PROTOBUF_H__ */
diff --git a/protobuf.c b/protobuf.c
index 5970494..486e0f2 100644
--- a/protobuf.c
+++ b/protobuf.c
@@ -3,6 +3,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
+#include <limits.h>
 
 #include <google/protobuf-c/protobuf-c.h>
 
@@ -20,33 +21,39 @@
  */
 #define PB_PKOBJ_LOCAL_SIZE	1024
 
+#ifdef CONFIG_X86_64
+#define PRETTY_ARRAY_TO_PTR(ptr)	((void *)((unsigned long)ptr & LONG_MAX))
+#define IS_PRETTY_ARRAY(ptr)		((unsigned long)ptr & ~LONG_MAX)
+#endif
+
 struct pb_pr_ctrl_s {
 	void *arg;
 	int single_entry;
 	int depth;
+	int field_nr;
+	const pb_pr_field_t *pretty_array;
 };
 
 typedef struct pb_pr_ctrl_s pb_pr_ctl_t;
-typedef void (pb_pr_field_t)(void *obj, pb_pr_ctl_t *ctl);
 
-static void pb_msg_int32x(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_int32x(void *obj, void *ctl)
 {
 	pr_msg("0x%08x", *(int *)obj);
 }
 
-static void pb_msg_int64x(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_int64x(void *obj, void *ctl)
 {
 	pr_msg("0x%016lx", *(long *)obj);
 }
 
-static void pb_msg_string(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_string(void *obj, void *ctl)
 {
 	pr_msg("\"%s\"",	*(char **)obj);
 }
 
-static void pb_msg_unk(void *obj, pb_pr_ctl_t *ctl)
+static void pb_msg_unk(void *obj, void *ctl)
 {
-	pr_msg("unknown object %p\n", obj);
+	pr_msg("unknown object %p", obj);
 }
 
 static inline void print_tabs(pb_pr_ctl_t *ctl)
@@ -62,6 +69,8 @@ static inline void print_tabs(pb_pr_ctl_t *ctl)
 
 static void print_nested_message_braces(pb_pr_ctl_t *ctl, int right_brace)
 {
+	if (ctl->pretty_array)
+		return;
 	if (right_brace)
 		print_tabs(ctl);
 	pr_msg("%s%s", (right_brace) ? "}" : "{", (ctl->single_entry) ? "\n" : " ");
@@ -69,17 +78,27 @@ static void print_nested_message_braces(pb_pr_ctl_t *ctl, int right_brace)
 
 static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl);
 
-static void show_nested_message(void *msg, pb_pr_ctl_t *ctl)
+static void show_nested_message(void *msg, void *arg)
 {
-	print_nested_message_braces(ctl, 0);
-	ctl->depth++;
-	pb_show_msg(msg, ctl);
-	ctl->depth--;
-	print_nested_message_braces(ctl, 1);
+	pb_pr_ctl_t *pctl = arg;
+	pb_pr_ctl_t ctl = {
+		.arg		= pctl->arg,
+		.single_entry	= pctl->single_entry,
+		.depth		= pctl->depth + 1,
+		.field_nr	= 0,
+	};
+
+	if (pctl->pretty_array)
+		ctl.pretty_array = PRETTY_ARRAY_TO_PTR(pctl->pretty_array[pctl->field_nr]);
+
+	print_nested_message_braces(&ctl, 0);
+	pb_show_msg(msg, &ctl);
+	print_nested_message_braces(&ctl, 1);
 }
 
-static void show_enum(void *msg, pb_pr_ctl_t *ctl)
+static void show_enum(void *msg, void *arg)
 {
+	pb_pr_ctl_t *ctl = arg;
 	ProtobufCEnumDescriptor *d = ctl->arg;
 	const char *val_name = NULL;
 	int val, i;
@@ -129,13 +148,13 @@ static size_t get_field_size(int type)
 static void pb_show_field(const ProtobufCFieldDescriptor *fd, void *where,
 			  unsigned long nr_fields, pb_pr_ctl_t *ctl)
 {
-	pb_pr_field_t *show;
+	pb_pr_field_t show;
 	unsigned long counter;
 	size_t fsize = get_field_size(fd->type);
 
-	print_tabs(ctl);
+	pb_pr_field_t pretty = NULL;
 
-	pr_msg("%s: ", fd->name);
+	BUG_ON(fsize == 0);
 
 	switch (fd->type) {
 		case PROTOBUF_C_TYPE_INT32:
@@ -174,6 +193,15 @@ static void pb_show_field(const ProtobufCFieldDescriptor *fd, void *where,
 			break;
 	}
 
+	if (ctl->pretty_array) {
+		pretty = ctl->pretty_array[ctl->field_nr];
+		if (pretty && !IS_PRETTY_ARRAY(pretty))
+			show = pretty;
+	} else {
+		print_tabs(ctl);
+		pr_msg("%s: ", fd->name);
+	}
+
 	show(where, ctl);
 	where += fsize;
 
@@ -182,10 +210,12 @@ static void pb_show_field(const ProtobufCFieldDescriptor *fd, void *where,
 		show(where, ctl);
 	}
 
-	if (ctl->single_entry)
-		pr_msg("\n");
-	else
-		pr_msg(" ");
+	if (!pretty) {
+		if (ctl->single_entry)
+			pr_msg("\n");
+		else
+			pr_msg(" ");
+	}
 }
 
 static int pb_optional_field_present(const ProtobufCFieldDescriptor *field,
@@ -208,13 +238,12 @@ static int pb_optional_field_present(const ProtobufCFieldDescriptor *field,
 
 static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl)
 {
-	int i;
 	const ProtobufCMessageDescriptor *md = ctl->arg;
 
 	BUG_ON(md == NULL);
 
-	for (i = 0; i < md->n_fields; i++) {
-		const ProtobufCFieldDescriptor fd = md->fields[i];
+	for (ctl->field_nr = 0; ctl->field_nr < md->n_fields; ctl->field_nr++) {
+		const ProtobufCFieldDescriptor fd = md->fields[ctl->field_nr];
 		unsigned long *data;
 		size_t nr_fields;
 
@@ -240,9 +269,12 @@ static inline void pb_no_payload(int fd, void *obj, int flags) { }
 void do_pb_show_plain(int fd, const ProtobufCMessageDescriptor *md,
 		pb_unpack_t unpack, pb_free_t free, int single_entry,
 		void (*payload_hadler)(int fd, void *obj, int flags),
-		int flags)
+		int flags, pb_pr_field_t *pretty_array)
 {
-	pb_pr_ctl_t ctl = {NULL, single_entry, 0};
+	pb_pr_ctl_t ctl = {
+		.single_entry = single_entry, 
+		.pretty_array = pretty_array,
+	};
 	void (*handle_payload)(int fd, void *obj, int flags);
 
 	handle_payload = (payload_hadler) ? : pb_no_payload;



More information about the CRIU mailing list