From 1c7bc28d35db1fe2edb8ecc7394df713be2ff970 Mon Sep 17 00:00:00 2001 From: Amnon Heiman Date: Tue, 1 Mar 2016 03:35:42 +0200 Subject: [PATCH] idl-compiler: change optional vector implementation This patch change the way optional vector are implemented. Now a vector of optional would be handle like any other non primitive types, with a single method add() that would return a writer to the optional. The writer to the optional would have a skip and write method like simple optional field. For basic types the write method would get the value as a parameter, for composite type, it would return a writer to the type. Signed-off-by: Amnon Heiman Message-Id: <1456796143-3366-2-git-send-email-amnon@scylladb.com> --- idl-compiler.py | 83 +++++++++++++++++++++++++++++++++---------- mutation_partition.cc | 10 +++--- 2 files changed, 69 insertions(+), 24 deletions(-) diff --git a/idl-compiler.py b/idl-compiler.py index fe7b8a51be..307489329f 100755 --- a/idl-compiler.py +++ b/idl-compiler.py @@ -30,6 +30,7 @@ import pyparsing as pp from functools import reduce import textwrap from numbers import Number +from timeit import reindent EXTENSION = '.idl.hh' READ_BUFF = 'input_buffer' @@ -218,6 +219,16 @@ def param_type(lst): return lst[0] return lst[0] + join_template(lst[1]) +def flat_template(lst): + return ", ".join([param_type(l) for l in lst]) + +def flat_type(lst): + if isinstance(lst, str): + return lst + if len(lst) == 1: + return flat_type(lst[0]) + return (lst[0] + "__" + "_".join([flat_type(l) for l in lst[1]])).replace('::', '__') + def is_class(obj): return obj["type"] == "class" or obj["type"] == "struct" @@ -243,7 +254,7 @@ def is_basic_type(lst): if isinstance(lst, str): return lst not in local_types if len(lst) == 1: - return lst[0] not in local_types + return isinstance(lst[0], str) and lst[0] not in local_types return False def is_local_type(lst): @@ -330,39 +341,52 @@ struct $node_name { fprintln(hout, "};") -def vector_add_method(current, base_state): - if is_optional(current["type"][1][0]): - typ = current["type"][1][0] - res = reindent(4, """ - void write_empty() { +def optional_add_methods(typ): + res = reindent(4,""" + void skip() { serialize(_out, false); - _count++; - }""") - set_optional = "serialize(_out, true);" + }""") + if is_basic_type(typ): + added_type = typ + elif is_local_type(typ): + added_type = param_type(typ) + "_view" else: - typ = current["type"] - res = "" - set_optional = "" + print("non supported optional type ", typ) + raise "non supported optional type " + param_type(typ) + res = res + Template(reindent(4, """ + void write(const $type& obj) { + serialize(_out, true); + serialize(_out, obj); + }""")).substitute({'type' : added_type}) + if is_local_type(typ): + res = res + Template(reindent(4, """ + writer_of_$type write() { + serialize(_out, true); + return {_out}; + }""")).substitute({'type' : param_type(typ)}) + return res + + +def vector_add_method(current, base_state): + typ = current["type"] + res = "" if is_basic_type(typ[1]): res = res + Template(""" void add_$name($type t) { - $set_optional serialize(_out, t); _count++; - }""").substitute({'type': param_type(typ[1]), 'name': current["name"], 'set_optional': set_optional}) + }""").substitute({'type': param_type(typ[1][0]), 'name': current["name"]}) else: res = res + Template(""" writer_of_$type add() { - $set_optional _count++; return {_out}; - }""").substitute({'type': param_type(typ[1]), 'name': current["name"], 'set_optional': set_optional}) + }""").substitute({'type': flat_type(typ[1][0]), 'name': current["name"]}) res = res + Template(""" - void add(${type}_view v) { - $set_optional + void add(${type} v) { serialize(_out, v); _count++; - }""").substitute({'type': param_type(typ[1]), 'set_optional': set_optional}) + }""").substitute({'type': param_view_type(typ[1][0])}) return res + Template(""" after_${basestate}__$name end_$name() && { _size.set(_out, _count); @@ -548,8 +572,24 @@ struct $name { };""").substitute({'name': struct_name, 'state' : base_state, 'fun' : fun, 'vector_placeholder': vector_placeholder, 'constructor': constructor})) def add_vector_node(hout, member, base_state, parents): + if get_template_name(member["type"][1][0]): + add_template_writer_node(hout,member["type"][1][0] ) add_node(hout, base_state + "__" + member["name"], member["type"], base_state, "", parents, vector_add_method(member, base_state), True) +optional_nodes = set() + +def add_optional_node(hout, typ): + global optional_nodes + full_type = flat_type(typ) + if full_type in optional_nodes: + return + optional_nodes.add(full_type) + fprintln(hout, Template(reindent(0,""" +struct writer_of_$type { + bytes_ostream& _out; + $add_method +};""")).substitute({'type': full_type, 'add_method': optional_add_methods(typ[1][0])})) + def add_variant_nodes(hout, member, param, base_state, parents, classes): vr = False par = base_state + "__" + member["name"] @@ -572,6 +612,11 @@ def add_variant_nodes(hout, member, param, base_state, parents, classes): vr = True writers = set() +def add_template_writer_node(hout, typ): + if is_optional(typ): + add_optional_node(hout, typ) + + def add_nodes_when_needed(hout, info, member, base_state_name, parents, member_classes): if is_vector(member["type"]): add_vector_node(hout, member, base_state_name, base_state_name) diff --git a/mutation_partition.cc b/mutation_partition.cc index 22ee1737e1..8c6e2a3b49 100644 --- a/mutation_partition.cc +++ b/mutation_partition.cc @@ -397,7 +397,7 @@ void mutation_partition::for_each_row(const schema& schema, const query::range void write_cell(RowWriter& w, const query::partition_slice& slice, ::atomic_cell_view c) { assert(c.is_live()); - ser::writer_of_qr_cell wr = w.add(); + ser::writer_of_qr_cell wr = w.add().write(); auto after_timestamp = [&, wr = std::move(wr)] () mutable { if (slice.options.contains()) { return std::move(wr).write_timestamp(c.timestamp()); @@ -421,7 +421,7 @@ void write_cell(RowWriter& w, const query::partition_slice& slice, const data_ty if (slice.options.contains()) { ctype = map_type_impl::get_instance(ctype->name_comparator(), ctype->value_comparator(), true); } - w.add().skip_timestamp() + w.add().write().skip_timestamp() .skip_expiry() .write_value(ctype->to_value(v, slice.cql_format())) .end_qr_cell(); @@ -440,13 +440,13 @@ static void get_row_slice(const schema& s, for (auto id : columns) { const atomic_cell_or_collection* cell = cells.find_cell(id); if (!cell) { - writer.write_empty(); + writer.add().skip(); } else { auto&& def = s.column_at(kind, id); if (def.is_atomic()) { auto c = cell->as_atomic_cell(); if (!c.is_live(tomb, now)) { - writer.write_empty(); + writer.add().skip(); } else { write_cell(writer, slice, cell->as_atomic_cell()); } @@ -458,7 +458,7 @@ static void get_row_slice(const schema& s, // FIXME: Instead of this, write optimistically and retract if empty auto m_ser = ctype->serialize_mutation_form_only_live(m_view, now); if (ctype->is_empty(m_ser)) { - writer.write_empty(); + writer.add().skip(); } else { write_cell(writer, slice, def.type, m_ser); }