[ 
https://issues.apache.org/jira/browse/IGNITE-28940?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Anton Vinogradov updated IGNITE-28940:
--------------------------------------
    Labels: IEP-132 compatibility wire-format  (was: IEP-132 compatibility)

> Choose the marshaller by transport, not by message class
> --------------------------------------------------------
>
>                 Key: IGNITE-28940
>                 URL: https://issues.apache.org/jira/browse/IGNITE-28940
>             Project: Ignite
>          Issue Type: Sub-task
>          Components: messaging
>            Reporter: Anton Vinogradov
>            Assignee: Anton Vinogradov
>            Priority: Major
>              Labels: IEP-132, compatibility, wire-format
>             Fix For: 2.19
>
>
> *Wire format change. Do this before 2.19 is released - after that it would 
> break rolling upgrade.*
> h3. Goal
> Take the marshaller from the place where we marshal, not from the message 
> class.
> h3. Why
> Binary cannot be used where the marshalling cannot afford a cluster-wide 
> class registration, and that is a property of the call site.
> The registration itself is {{MarshallerContextImpl#registerClassName}} -> 
> {{proposeMapping}} -> {{fut.get()}}, which waits for discovery. Ignite 
> classes usually skip it, because 2276 names are pre-accepted from 
> {{META-INF/classnames.properties}}. But that list is not closed under 
> nesting: a plain {{CacheConfiguration}} needs 9 types registered and two of 
> them are absent - 
> {{javax.cache.configuration.FactoryBuilder$SingletonFactory}} and 
> {{javax.cache.expiry.EternalExpiryPolicy}}, both coming from the default 
> expiry policy. A discovery message carrying a cache configuration would 
> therefore register types from inside the discovery thread.
> Measured on the same objects, binary is the better marshaller *when types are 
> registered*: node attributes 2423 bytes / 5.2 us against 2725 / 30.0 for jdk, 
> {{CacheConfiguration}} 857 bytes against 4539. So the split is not "binary is 
> for user data" - it is "binary needs a place where registration is allowed". 
> User classes travel with jdk in a dozen places today - 
> {{TcpDiscoveryNode#attrs}} and {{#consistentId}}, {{StoredCacheData#ccfg}} 
> and {{#qryEntities}}, {{DynamicCacheChangeRequest#startCfg}}, 
> {{LazyServiceConfigurationMessage#affKey}}, 
> {{QueryEntityMessage#dfltFieldValues}}, {{PluginsDataBagItem#data}}, 
> {{SerializableDataBagItemWrapper#data}}, 
> {{PartitionHashRecord#consistentId}}, {{TransactionsHashRecord}} and 
> {{ErrorMessage#err}} - the full list is in IGNITE-28935.
> The call sites are already separated by transport, and transport is a 
> reliable indicator of that:
> * communication - {{GridIoManager}} (marshal on send and the unmarshal 
> paths), {{GridCacheIoManager}}, {{IgniteTxManager}}, 
> {{GridDhtPartitionsExchangeFuture}}, {{CacheContinuousQueryHandler}}, 
> {{DataStreamProcessor}}, calcite {{MessageServiceImpl}};
> * discovery - {{TcpDiscoveryIoSession}} and ZooKeeper 
> {{DiscoveryMessageParser}}.
> The hand-written half of the API already works this way: 
> {{MarshallableMessage#marshal(Marshaller)}} takes the marshaller as a 
> parameter. Only generated code keeps it in a field, which is what pins it to 
> the class.
> h3. How
> * add a {{Marshaller}} parameter to {{MessageMarshaller}} and 
> {{MessageMarshalling}}; the generator stops storing it and passes it to 
> nested messages;
> * communication call sites pass {{ctx.marshaller()}}, discovery call sites 
> pass {{marshallerContext().jdkMarshaller()}};
> * delete {{@UseBinaryMarshaller}}, 
> {{AbstractMarshallableMessageFactoryProvider#init}} and both marshaller 
> fields.
> The wire format changes for four classes, deliberately:
> * {{ErrorMessage}}, {{PartitionHashRecord}} and {{TransactionsHashRecord}}: 
> jdk to binary. This is safe for {{ErrorMessage}}, because 
> {{java.lang.Throwable}} declares {{writeObject}} and {{readObject}}. Every 
> exception matches {{isCustomJavaSerialization}}, so binary passes it to 
> {{OptimizedMarshaller}}: 709 bytes with jdk against 715 with binary, 6.7 us 
> against 7.4. The bytes change, the behaviour does not.
> * {{BinaryMetadataVersionInfo}}: binary to jdk, the same as 
> {{MetadataUpdateProposedMessage}}. Not needed if IGNITE-28939 is done first.
> Note: {{MessageMarshaller}} is in the public package 
> {{org.apache.ignite.plugin.extensions.communication}}. Outside the generator 
> only three tests implement it.
> h3. Expected result
> No annotations left. One marshaller is used for the whole message tree of one 
> send, so a wrong marshaller from inheritance or from nesting is not possible. 
> When the set of pre-registered types changes, or a self-contained binary mode 
> appears, only the call sites have to be revisited - not sixty classes.
> h3. How to verify
> Run All. Also continuous queries, idle_verify, {{DistributedProcess}} and 
> calcite. Add a test that sends the same message type over both transports.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to