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 <amnon@scylladb.com>
Message-Id: <1456796143-3366-2-git-send-email-amnon@scylladb.com>
This commit is contained in:
Amnon Heiman
2016-03-01 03:35:42 +02:00
committed by Avi Kivity
parent 0de8f6d24f
commit 1c7bc28d35
2 changed files with 69 additions and 24 deletions

View File

@@ -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)

View File

@@ -397,7 +397,7 @@ void mutation_partition::for_each_row(const schema& schema, const query::range<c
template<typename RowWriter>
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<query::partition_slice::option::send_timestamp>()) {
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<query::partition_slice::option::collections_as_maps>()) {
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);
}