diff options
author | Jason Chan <jason.chan@mongodb.com> | 2022-08-15 14:15:39 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-08-15 15:32:50 +0000 |
commit | abca3f700aa1da45ea14c8f2dc6ab52f952e3945 (patch) | |
tree | 47e72b505dc1663f929d56e625bc650df27ad305 /buildscripts | |
parent | cf52d18cc9aa016ae978786f4b9e99c12d1b582b (diff) | |
download | mongo-abca3f700aa1da45ea14c8f2dc6ab52f952e3945.tar.gz |
Revert "SERVER-67826 Ensure parsed IDL types own or preserve the lifetime of their data"
This reverts commit de251a83a41566723a895bf1106c66d9f19d1540.
Diffstat (limited to 'buildscripts')
-rw-r--r-- | buildscripts/idl/idl/generator.py | 120 | ||||
-rw-r--r-- | buildscripts/idl/idl/struct_types.py | 55 |
2 files changed, 27 insertions, 148 deletions
diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py index 79928b29ab9..a4ea20a4a33 100644 --- a/buildscripts/idl/idl/generator.py +++ b/buildscripts/idl/idl/generator.py @@ -36,21 +36,12 @@ import re import sys import textwrap from abc import ABCMeta, abstractmethod -from enum import Enum from typing import Dict, Iterable, List, Mapping, Tuple, Union, cast from . import (ast, bson, common, cpp_types, enum_types, generic_field_list_types, struct_types, writer) -class _StructDataOwnership(Enum): - """Enumerates the ways a struct may participate in ownership of it's data.""" - - VIEW = 1 # Doesn't participate in ownership - SHARED = 2 # Participates in non-exclusive ownership - OWNER = 3 # Takes ownership of underlying data - - def _get_field_member_name(field): # type: (ast.Field) -> str """Get the C++ class member name for a field.""" @@ -479,64 +470,26 @@ class _CppHeaderFileWriter(_CppFileWriterBase): def gen_serializer_methods(self, struct): # type: (ast.Struct) -> None - """Generate serializer method declarations.""" - struct_type_info = struct_types.get_struct_info(struct) - self._writer.write_line(struct_type_info.get_serializer_method().get_declaration()) + """Generate a serializer method declarations.""" - maybe_op_msg_serializer = struct_type_info.get_op_msg_request_serializer_method() - if maybe_op_msg_serializer: - self._writer.write_line(maybe_op_msg_serializer.get_declaration()) + struct_type_info = struct_types.get_struct_info(struct) - self._writer.write_line(struct_type_info.get_to_bson_method().get_declaration()) + parse_method = struct_type_info.get_deserializer_static_method() + if parse_method: + self._writer.write_line(parse_method.get_declaration()) - self._writer.write_empty_line() + parse_method = struct_type_info.get_op_msg_request_deserializer_static_method() + if parse_method: + self._writer.write_line(parse_method.get_declaration()) - def gen_deserializer_methods(self, struct): - # type: (ast.Struct) -> None - """Generate deserializer method declarations.""" - struct_type_info = struct_types.get_struct_info(struct) - possible_deserializer_methods = [ - struct_type_info.get_deserializer_static_method(), - struct_type_info.get_owned_deserializer_static_method(), - struct_type_info.get_sharing_deserializer_static_method(), - struct_type_info.get_op_msg_request_deserializer_static_method() - ] - for maybe_parse_method in possible_deserializer_methods: - if maybe_parse_method: - comment = maybe_parse_method.get_desc_for_comment() - if comment: - self.gen_description_comment(comment) - self._writer.write_line(maybe_parse_method.get_declaration()) + self._writer.write_line(struct_type_info.get_serializer_method().get_declaration()) - self._writer.write_empty_line() + parse_method = struct_type_info.get_op_msg_request_serializer_method() + if parse_method: + self._writer.write_line(parse_method.get_declaration()) - def gen_ownership_getter(self): - # type: () -> None - """Generate a getter that returns true if this IDL object owns its underlying data.""" - self.gen_description_comment( - textwrap.dedent("""\ - An IDL struct can either provide a view onto some underlying BSON data, or it can - participate in owning that data. This function returns true if the struct participates in - owning the underlying data. - - Note that the underlying data is not synchronized with the IDL struct over its lifetime; to - generate a BSON representation of an IDL struct, use its `serialize` member functions. - Participating in ownership of the underlying data merely allows the struct to ensure that - struct members that are pointers-into-BSON (i.e. BSONElement and BSONObject) are valid for - the lifetime of the struct itself.""")) - self._writer.write_line("bool isOwned() const { return _anchorObj.isOwned(); }") - - def gen_private_ownership_setters(self): - # type: () -> None - """Generate a setter that can be used to allow this IDL struct to particpate in the ownership of some BSON that the struct's members refer to.""" - with self._block('void setAnchor(const BSONObj& obj) {', '}'): - self._writer.write_line("invariant(obj.isOwned());") - self._writer.write_line("_anchorObj = obj;") - self._writer.write_empty_line() + self._writer.write_line(struct_type_info.get_to_bson_method().get_declaration()) - with self._block('void setAnchor(BSONObj&& obj) {', '}'): - self._writer.write_line("invariant(obj.isOwned());") - self._writer.write_line("_anchorObj = std::move(obj);") self._writer.write_empty_line() def gen_protected_serializer_methods(self, struct): @@ -1122,14 +1075,9 @@ class _CppHeaderFileWriter(_CppFileWriterBase): # Write serialization self.gen_serializer_methods(struct) - # Write deserialization - self.gen_deserializer_methods(struct) - if isinstance(struct, ast.Command): self.gen_op_msg_request_methods(struct) - self.gen_ownership_getter() - # Write getters & setters for field in struct.fields: if not field.ignore: @@ -1155,8 +1103,6 @@ class _CppHeaderFileWriter(_CppFileWriterBase): self.write_unindented_line('private:') - self.gen_private_ownership_setters() - if struct.generate_comparison_operators: self.gen_comparison_operators_declarations(struct) @@ -1172,8 +1118,6 @@ class _CppHeaderFileWriter(_CppFileWriterBase): if not field.ignore and not field.chained_struct_field: self.gen_member(field) - self._writer.write_line("BSONObj _anchorObj;") - # Write serializer member variables # Note: we write these out second to ensure the bit fields can be packed by # the compiler. @@ -1759,9 +1703,8 @@ class _CppSourceFileWriter(_CppFileWriterBase): return field_usage_check - def get_bson_deserializer_static_common(self, struct, static_method_info, method_info, - ownership): - # type: (ast.Struct, struct_types.MethodInfo, struct_types.MethodInfo, _StructDataOwnership) -> None + def get_bson_deserializer_static_common(self, struct, static_method_info, method_info): + # type: (ast.Struct, struct_types.MethodInfo, struct_types.MethodInfo) -> None """Generate the C++ deserializer static method.""" # pylint: disable=invalid-name func_def = static_method_info.get_definition() @@ -1795,17 +1738,8 @@ class _CppSourceFileWriter(_CppFileWriterBase): common.title_case(struct.cpp_name)) self._writer.write_line(method_info.get_call('object')) - - if ownership == _StructDataOwnership.OWNER: - self._writer.write_line('object.setAnchor(std::move(bsonObject));') - - elif ownership == _StructDataOwnership.SHARED: - self._writer.write_line('object.setAnchor(bsonObject);') - self._writer.write_line('return object;') - self.write_empty_line() - def _compare_and_return_status(self, op, limit, field, optional_param): # type: (str, ast.Expression, ast.Field, str) -> None """Throw an error on comparison failure.""" @@ -1865,29 +1799,20 @@ class _CppSourceFileWriter(_CppFileWriterBase): # type: (ast.Struct) -> None """Generate the C++ deserializer method definitions.""" struct_type_info = struct_types.get_struct_info(struct) - method = struct_type_info.get_deserializer_method() self.get_bson_deserializer_static_common(struct, struct_type_info.get_deserializer_static_method(), - method, _StructDataOwnership.VIEW) - self.get_bson_deserializer_static_common( - struct, struct_type_info.get_sharing_deserializer_static_method(), method, - _StructDataOwnership.SHARED) - self.get_bson_deserializer_static_common( - struct, struct_type_info.get_owned_deserializer_static_method(), method, - _StructDataOwnership.OWNER) - - func_def = method.get_definition() - - # Name of the variable that we are deserialzing from - variable_name = "bsonObject" + struct_type_info.get_deserializer_method()) + func_def = struct_type_info.get_deserializer_method().get_definition() with self._block('%s {' % (func_def), '}'): + # If the struct contains no fields, there's nothing to deserialize, so we write an empty function stub. if not struct.fields: return - field_usage_check = self._gen_fields_deserializer_common(struct, variable_name) + # Deserialize all the fields + field_usage_check = self._gen_fields_deserializer_common(struct, "bsonObject") # Check for required fields field_usage_check.add_final_checks() @@ -1896,7 +1821,7 @@ class _CppSourceFileWriter(_CppFileWriterBase): if struct.cpp_validator_func is not None: self._writer.write_line(struct.cpp_validator_func + "(this);") - self._gen_command_deserializer(struct, variable_name) + self._gen_command_deserializer(struct, "bsonObject") def gen_op_msg_request_deserializer_methods(self, struct): # type: (ast.Struct) -> None @@ -1911,7 +1836,7 @@ class _CppSourceFileWriter(_CppFileWriterBase): self.get_bson_deserializer_static_common( struct, struct_type_info.get_op_msg_request_deserializer_static_method(), - struct_type_info.get_op_msg_request_deserializer_method(), _StructDataOwnership.VIEW) + struct_type_info.get_op_msg_request_deserializer_method()) func_def = struct_type_info.get_op_msg_request_deserializer_method().get_definition() with self._block('%s {' % (func_def), '}'): @@ -2785,6 +2710,7 @@ class _CppSourceFileWriter(_CppFileWriterBase): self.gen_field_validators(struct) self.write_empty_line() + # Write deserializers self.gen_bson_deserializer_methods(struct) self.write_empty_line() diff --git a/buildscripts/idl/idl/struct_types.py b/buildscripts/idl/idl/struct_types.py index 339defab4e2..6aeb1760db0 100644 --- a/buildscripts/idl/idl/struct_types.py +++ b/buildscripts/idl/idl/struct_types.py @@ -27,7 +27,6 @@ # """Provide code generation information for structs and commands in a polymorphic way.""" -import textwrap from abc import ABCMeta, abstractmethod from typing import Optional, List @@ -81,11 +80,9 @@ class ArgumentInfo(object): class MethodInfo(object): """Class that encapslates information about a method and how to declare, define, and call it.""" - # pylint: disable=too-many-instance-attributes - def __init__(self, class_name, method_name, args, return_type=None, static=False, const=False, - explicit=False, desc_for_comment=None): - # type: (str, str, List[str], str, bool, bool, bool, Optional[str]) -> None + explicit=False): + # type: (str, str, List[str], str, bool, bool, bool) -> None # pylint: disable=too-many-arguments """Create a MethodInfo instance.""" self.class_name = class_name @@ -95,7 +92,6 @@ class MethodInfo(object): self.static = static self.const = const self.explicit = explicit - self.desc_for_comment = desc_for_comment def get_declaration(self): # type: () -> str @@ -142,7 +138,7 @@ class MethodInfo(object): def get_call(self, obj): # type: (Optional[str]) -> str - """Generate a simple call to the method using the defined args list.""" + """Generate a simply call to the method using the defined args list.""" args = ', '.join([arg.name for arg in self.args]) @@ -153,11 +149,6 @@ class MethodInfo(object): return common.template_args("${method_name}(${args});", method_name=self.method_name, args=args) - def get_desc_for_comment(self): - # type: () -> Optional[str] - """Get the description of this method suitable for commenting it.""" - return self.desc_for_comment - class StructTypeInfoBase(object, metaclass=ABCMeta): """Base class for struct and command code generation.""" @@ -193,18 +184,6 @@ class StructTypeInfoBase(object, metaclass=ABCMeta): pass @abstractmethod - def get_sharing_deserializer_static_method(self): - # type: () -> MethodInfo - """Get the public static deserializer method for a struct that participates in shared ownership of underlying data we are deserializing from.""" - pass - - @abstractmethod - def get_owned_deserializer_static_method(self): - # type: () -> MethodInfo - """Get the public static deserializer method for a struct that takes exclusive ownership of underlying data we are deserializing from.""" - pass - - @abstractmethod def get_deserializer_method(self): # type: () -> MethodInfo """Get the protected deserializer method for a struct.""" @@ -274,38 +253,12 @@ class _StructTypeInfo(StructTypeInfoBase): class_name = common.title_case(self._struct.cpp_name) return MethodInfo(class_name, class_name, _get_required_parameters(self._struct)) - def get_sharing_deserializer_static_method(self): - # type: () -> MethodInfo - class_name = common.title_case(self._struct.cpp_name) - comment = textwrap.dedent(f"""\ - Factory function that parses a {class_name} from a BSONObj. A {class_name} parsed - this way participates in ownership of the data underlying the BSONObj.""") - return MethodInfo(class_name, 'parseSharingOwnership', - ['const IDLParserContext& ctxt', 'const BSONObj& bsonObject'], class_name, - static=True, desc_for_comment=comment) - - def get_owned_deserializer_static_method(self): - # type: () -> MethodInfo - class_name = common.title_case(self._struct.cpp_name) - comment = textwrap.dedent(f"""\ - Factory function that parses a {class_name} from a BSONObj. A {class_name} parsed - this way takes ownership of the data underlying the BSONObj.""") - return MethodInfo(class_name, 'parseOwned', - ['const IDLParserContext& ctxt', 'BSONObj&& bsonObject'], class_name, - static=True, desc_for_comment=comment) - def get_deserializer_static_method(self): # type: () -> MethodInfo class_name = common.title_case(self._struct.cpp_name) - comment = textwrap.dedent(f"""\ - Factory function that parses a {class_name} from a BSONObj. A {class_name} parsed - this way is strictly a view onto that BSONObj; the BSONObj must be kept valid to - ensure the validity any members of this struct that point-into the BSONObj (i.e. - unowned - objects).""") return MethodInfo(class_name, 'parse', ['const IDLParserContext& ctxt', 'const BSONObj& bsonObject'], class_name, - static=True, desc_for_comment=comment) + static=True) def get_deserializer_method(self): # type: () -> MethodInfo |