[JBoss JIRA] (JGRP-2231) Intermittent NPE in JGroups GMS#up on shutdown
by Bela Ban (JIRA)
[ https://issues.jboss.org/browse/JGRP-2231?page=com.atlassian.jira.plugin.... ]
Bela Ban updated JGRP-2231:
---------------------------
Affects Version/s: 4.0.8
(was: 4.0.9)
> Intermittent NPE in JGroups GMS#up on shutdown
> ----------------------------------------------
>
> Key: JGRP-2231
> URL: https://issues.jboss.org/browse/JGRP-2231
> Project: JGroups
> Issue Type: Bug
> Affects Versions: 3.6.14, 4.0.8
> Reporter: Radoslav Husar
> Assignee: Radoslav Husar
> Priority: Minor
> Fix For: 4.0.9
>
> Attachments: server.log, standalone-ha.xml
>
>
> During mod_cluster failover due application undeploy on Solaris 10 intermittently I can see NPE \[1\].
> I've seen it already several times during failover with HTTPD with mod_cluster as balancer and EAP 7.1 as workers where their communication works over SSL which is configured using elytron on EAP side. I have seen the issue on Solaris 10 sparc (two different slaves).
> \[1\]
> {noformat}
> 2017-10-27 12:12:07,546 ERROR [org.jgroups.protocols.pbcast.GMS] (thread-2) JGRP000027: failed passing message up: java.lang.NullPointerException
> at org.jgroups.protocols.pbcast.GMS.up(GMS.java:895)
> at org.jgroups.stack.Protocol.up(Protocol.java:418)
> at org.jgroups.protocols.pbcast.STABLE.up(STABLE.java:294)
> at org.jgroups.protocols.UNICAST3.up(UNICAST3.java:487)
> at org.jgroups.protocols.pbcast.NAKACK2.deliverBatch(NAKACK2.java:989)
> at org.jgroups.protocols.pbcast.NAKACK2.removeAndPassUp(NAKACK2.java:919)
> at org.jgroups.protocols.pbcast.NAKACK2.handleMessage(NAKACK2.java:851)
> at org.jgroups.protocols.pbcast.NAKACK2.up(NAKACK2.java:611)
> at org.jgroups.protocols.VERIFY_SUSPECT.up(VERIFY_SUSPECT.java:155)
> at org.jgroups.protocols.FD_ALL.up(FD_ALL.java:200)
> at org.jgroups.protocols.FD_SOCK.up(FD_SOCK.java:325)
> at org.jgroups.protocols.MERGE3.up(MERGE3.java:292)
> at org.jgroups.protocols.Discovery.up(Discovery.java:296)
> at org.jgroups.protocols.TP.passMessageUp(TP.java:1657)
> at org.jgroups.protocols.TP$SingleMessageHandler.run(TP.java:1872)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at org.jboss.as.clustering.jgroups.ClassLoaderThreadFactory.lambda$newThread$0(ClassLoaderThreadFactory.java:52)
> at java.lang.Thread.run(Thread.java:748)
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (JGRP-2231) Intermittent NPE in JGroups GMS#up on shutdown
by Bela Ban (JIRA)
[ https://issues.jboss.org/browse/JGRP-2231?page=com.atlassian.jira.plugin.... ]
Bela Ban updated JGRP-2231:
---------------------------
Fix Version/s: 4.0.9
> Intermittent NPE in JGroups GMS#up on shutdown
> ----------------------------------------------
>
> Key: JGRP-2231
> URL: https://issues.jboss.org/browse/JGRP-2231
> Project: JGroups
> Issue Type: Bug
> Affects Versions: 3.6.14, 4.0.8
> Reporter: Radoslav Husar
> Assignee: Radoslav Husar
> Priority: Minor
> Fix For: 4.0.9
>
> Attachments: server.log, standalone-ha.xml
>
>
> During mod_cluster failover due application undeploy on Solaris 10 intermittently I can see NPE \[1\].
> I've seen it already several times during failover with HTTPD with mod_cluster as balancer and EAP 7.1 as workers where their communication works over SSL which is configured using elytron on EAP side. I have seen the issue on Solaris 10 sparc (two different slaves).
> \[1\]
> {noformat}
> 2017-10-27 12:12:07,546 ERROR [org.jgroups.protocols.pbcast.GMS] (thread-2) JGRP000027: failed passing message up: java.lang.NullPointerException
> at org.jgroups.protocols.pbcast.GMS.up(GMS.java:895)
> at org.jgroups.stack.Protocol.up(Protocol.java:418)
> at org.jgroups.protocols.pbcast.STABLE.up(STABLE.java:294)
> at org.jgroups.protocols.UNICAST3.up(UNICAST3.java:487)
> at org.jgroups.protocols.pbcast.NAKACK2.deliverBatch(NAKACK2.java:989)
> at org.jgroups.protocols.pbcast.NAKACK2.removeAndPassUp(NAKACK2.java:919)
> at org.jgroups.protocols.pbcast.NAKACK2.handleMessage(NAKACK2.java:851)
> at org.jgroups.protocols.pbcast.NAKACK2.up(NAKACK2.java:611)
> at org.jgroups.protocols.VERIFY_SUSPECT.up(VERIFY_SUSPECT.java:155)
> at org.jgroups.protocols.FD_ALL.up(FD_ALL.java:200)
> at org.jgroups.protocols.FD_SOCK.up(FD_SOCK.java:325)
> at org.jgroups.protocols.MERGE3.up(MERGE3.java:292)
> at org.jgroups.protocols.Discovery.up(Discovery.java:296)
> at org.jgroups.protocols.TP.passMessageUp(TP.java:1657)
> at org.jgroups.protocols.TP$SingleMessageHandler.run(TP.java:1872)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at org.jboss.as.clustering.jgroups.ClassLoaderThreadFactory.lambda$newThread$0(ClassLoaderThreadFactory.java:52)
> at java.lang.Thread.run(Thread.java:748)
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (WFCORE-3390) WARN logged during server shutdown when Elytron JACC is set
by Ondrej Kotek (JIRA)
[ https://issues.jboss.org/browse/WFCORE-3390?page=com.atlassian.jira.plugi... ]
Ondrej Kotek moved JBEAP-13657 to WFCORE-3390:
----------------------------------------------
Project: WildFly Core (was: JBoss Enterprise Application Platform)
Key: WFCORE-3390 (was: JBEAP-13657)
Workflow: GIT Pull Request workflow (was: CDW with loose statuses v1)
Component/s: Security
(was: Security)
Affects Version/s: 3.0.9.Final
(was: 7.1.0.CR3)
> WARN logged during server shutdown when Elytron JACC is set
> -----------------------------------------------------------
>
> Key: WFCORE-3390
> URL: https://issues.jboss.org/browse/WFCORE-3390
> Project: WildFly Core
> Issue Type: Bug
> Components: Security
> Affects Versions: 3.0.9.Final
> Reporter: Ondrej Kotek
> Priority: Critical
>
> When Elytron JACC policy resource is defined, there is WARN logged during server shutdown:
> {{WARN [org.wildfly.security] (MSC service thread 1-8) ELY08509: Calling any of the Policy.getPermissions() methods is not supported; please see the Java Authorization Contract for Containers (JACC) specification (section "1.4 Requirements", item 1) and the Java SE API specification for the Policy.getPermissions() methods for more information. Instead, use the Policy.implies() method for authorization checking.}}
> This is suspicious behaviour. Customers that monitor logs for warnings have to deal with this. Setting Critical.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (JGRP-2231) Intermittent NPE in JGroups GMS#up on shutdown
by Radoslav Husar (JIRA)
[ https://issues.jboss.org/browse/JGRP-2231?page=com.atlassian.jira.plugin.... ]
Radoslav Husar moved JBEAP-13655 to JGRP-2231:
----------------------------------------------
Project: JGroups (was: JBoss Enterprise Application Platform)
Key: JGRP-2231 (was: JBEAP-13655)
Workflow: GIT Pull Request workflow (was: CDW with loose statuses v1)
Component/s: (was: Clustering)
Affects Version/s: 4.0.8
3.6.14
(was: 7.1.0.CR3)
> Intermittent NPE in JGroups GMS#up on shutdown
> ----------------------------------------------
>
> Key: JGRP-2231
> URL: https://issues.jboss.org/browse/JGRP-2231
> Project: JGroups
> Issue Type: Bug
> Affects Versions: 4.0.8, 3.6.14
> Reporter: Radoslav Husar
> Assignee: Radoslav Husar
> Priority: Minor
> Attachments: server.log, standalone-ha.xml
>
>
> During mod_cluster failover due application undeploy on Solaris 10 intermittently I can see NPE \[1\].
> I've seen it already several times during failover with HTTPD with mod_cluster as balancer and EAP 7.1 as workers where their communication works over SSL which is configured using elytron on EAP side. I have seen the issue on Solaris 10 sparc (two different slaves).
> \[1\]
> {noformat}
> 2017-10-27 12:12:07,546 ERROR [org.jgroups.protocols.pbcast.GMS] (thread-2) JGRP000027: failed passing message up: java.lang.NullPointerException
> at org.jgroups.protocols.pbcast.GMS.up(GMS.java:895)
> at org.jgroups.stack.Protocol.up(Protocol.java:418)
> at org.jgroups.protocols.pbcast.STABLE.up(STABLE.java:294)
> at org.jgroups.protocols.UNICAST3.up(UNICAST3.java:487)
> at org.jgroups.protocols.pbcast.NAKACK2.deliverBatch(NAKACK2.java:989)
> at org.jgroups.protocols.pbcast.NAKACK2.removeAndPassUp(NAKACK2.java:919)
> at org.jgroups.protocols.pbcast.NAKACK2.handleMessage(NAKACK2.java:851)
> at org.jgroups.protocols.pbcast.NAKACK2.up(NAKACK2.java:611)
> at org.jgroups.protocols.VERIFY_SUSPECT.up(VERIFY_SUSPECT.java:155)
> at org.jgroups.protocols.FD_ALL.up(FD_ALL.java:200)
> at org.jgroups.protocols.FD_SOCK.up(FD_SOCK.java:325)
> at org.jgroups.protocols.MERGE3.up(MERGE3.java:292)
> at org.jgroups.protocols.Discovery.up(Discovery.java:296)
> at org.jgroups.protocols.TP.passMessageUp(TP.java:1657)
> at org.jgroups.protocols.TP$SingleMessageHandler.run(TP.java:1872)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at org.jboss.as.clustering.jgroups.ClassLoaderThreadFactory.lambda$newThread$0(ClassLoaderThreadFactory.java:52)
> at java.lang.Thread.run(Thread.java:748)
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (DROOLS-2081) Drools Decision Table Templates doesn't work on Spring Boot
by Sebastian Simrodt (JIRA)
Sebastian Simrodt created DROOLS-2081:
-----------------------------------------
Summary: Drools Decision Table Templates doesn't work on Spring Boot
Key: DROOLS-2081
URL: https://issues.jboss.org/browse/DROOLS-2081
Project: Drools
Issue Type: Bug
Environment: Spring Boot
Reporter: Sebastian Simrodt
Assignee: Edson Tirelli
Priority: Minor
Spring Boot changes the classpath of files from
"com/example/spreadsheet.xls"
to
"BOOT-INF/classes/com/example/spreadsheet.xls"
Hence you do a string compare of the classpath, templates won't work on a Spring Boot Environment.
I guess the easiest way to fix it, would be to change equals to endsWith in
AbstractKieModule:addResourceToCompiler
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (WFLY-8817) The jboss.dist system property is not used in testsuite/integration/elytron module
by Yeray Borges (JIRA)
[ https://issues.jboss.org/browse/WFLY-8817?page=com.atlassian.jira.plugin.... ]
Yeray Borges reassigned WFLY-8817:
----------------------------------
Assignee: Tomaz Cerar (was: Yeray Borges)
> The jboss.dist system property is not used in testsuite/integration/elytron module
> ----------------------------------------------------------------------------------
>
> Key: WFLY-8817
> URL: https://issues.jboss.org/browse/WFLY-8817
> Project: WildFly
> Issue Type: Bug
> Components: Test Suite
> Reporter: Josef Cacek
> Assignee: Tomaz Cerar
> Priority: Critical
> Fix For: 11.0.0.Final
>
>
> Elytron testsuite module doesn't work correctly with the {{jboss.dist}} system property.
> The {{jboss.dist}} system property is used by QE to run the AS testsuite against the correct bits (e.g. comming from PROD team). The {{testsuite/integration/elytron}} module seems not to be taking this property into account. It seems it always uses output of {{wildfly-server-provisioning-maven-plugin}} to test against.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (JGRP-2218) New payload interface
by Bela Ban (JIRA)
[ https://issues.jboss.org/browse/JGRP-2218?page=com.atlassian.jira.plugin.... ]
Bela Ban updated JGRP-2218:
---------------------------
Description:
h3. Goal
Change payload in {{Message}} from byte[] arrays to a {{Payload}} interface which can have multiple implementations.
h3. Reason
Currently, having to pass a byte[] array to a message leads to unnecessary copying:
* When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
* When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
* When an object has to be sent (e.g. in Infinispan), the object has to be marshalled into a byte[] array (first allocation) and then added to the message. With the suggested {{ObjectPayload}} (below), marshalling of the object would occur late, and it would be marshalled directly into the output stream of the bundler, eliminating the byte[] array allocation made by the application.
h3. Design
Instead of copying, the application creates an instance of {{Payload}} and sets the payload in {{Message}}. The {{Payload}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of payload implementations, e.g.
* {{ByteArrayPayload}}: wraps a byte[] array with an offset and length
* {{NioDirectPayload}}: wraps an NIO direct {{ByteBuffer}}
* {{NioHeapPayload}}: wraps an NIO heap-based {{ByteBuffer}}
* {{CompositePayload}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
* {{IntPayload}}: a single integer
* {{ObjectPayload}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in payloads and they're only marshalled at the end (transport).
* {{PartialPayload}}: a ref to a {{Payload}}, with an offset and length
* {{InputStreamPayload}}: has a ref to an input stream and copies data from input- to output stream when marshalling
The {{Payload}} interface has methods:
* {{size()}}
* {{writeTo(DataOutput)}}
* {{readFrom(DataInput)}}
* {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying payload
and possibly also
* {{acquire()}} and
* {{release()}} (for ref-counting)
* {{copy()}}
Each payload impl has an ID and it should be possible to register new impls. A {{PayloadFactory}} maintains a mapping between IDs and impl classes.
When marshalling a {{Payload}}, the ID is written first, followed by the payload's {{writeTo()}} method. When reading payloads, the {{PayloadFactory}} is used to create instances from IDs.
h4. Fragmentation
When fragmenting a buffer, the fragments are instances of {{PartialPayload}} which maintains an offset and length over an underlying payload. When marshalling a {{PartialPayload}}, only the part between offset and offset+length is written to the output stream.
For fragmentation, method {{size()}} is crucial to determine whether a payload needs to be fragmented, or not. If, for example, a payload (e.g. an {{ObjectPayload}}) cannot determine the correct size, it may return {{-1}}. This leads to the {{ObjectPayload}} getting marshalled right away and getting wrapped into a {{ByteArrayPayload}}. So if {{size()}} cannot be determined, we have exactly the same behavior as what's currently done.
h4. Reference counting
If we implement ref-counting, then payloads can be reused as soon as the ref-count is 0. For example, when sending a message, the payload's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the payload cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the payload cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
h4. Payload factory
When a request is received, the buffer is created from the bytes received on the network, based on the ID. This should be done by asking a {{PayloadFactory}} component for a new buffer. A naive implementation might create a new buffer every time, but a more sophisticated one might use a pool of payloads.
The {{PayloadFactory}} instance could be replaced by one's own implementation; this allows for an application to control the lifecycle of payloads: thus the creation of buffers by the application and of payloads received over the network can be controlled by the same payload management impl.
h4. Symmetry
When sending a {{CompositePayload}} of a 500 byte {{ByteArrayPayload}} and a 1000 byte {{NioDirectPayload}}, would we want to also get the same {{CompositePayload}} consisting of 2 payloads on the receiver side, or would we want to combine the 2 payloads into one and make the 2 payloads refer to the same combined byte[] array (or NIO buffer)? Should this be made configurable?
h4. ObjectPayload
If ObjectPayload cannot determine the size of the serialized data, it should return {{-1}}. This means that {{Message.setPayload(ObjectPayload)}} would right away serialize {{ObjectPayload}} into {{ByteArrayPayload}}.
This means we do have the {{byte[]}} array creation (same as now), but for object payloads which do implement {{size()}} correctly, we could still do late serialization.
h5. ObjectPayload and fragmentation
{{FRAG3}} could decorate {{ObjectPayload}} with a fragmentation payload, which generates fragments on serialization and sends them down the stack.
h4. Misc
* Since this issue includes API changes, the version will be 5.0
was:
h3. Goal
Change payload in {{Message}} from byte[] arrays to a {{Payload}} interface which can have multiple implementations.
h3. Reason
Currently, having to pass a byte[] array to a message leads to unnecessary copying:
* When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
* When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
* When an object has to be sent (e.g. in Infinispan), the object has to be marshalled into a byte[] array (first allocation) and then added to the message. With the suggested {{ObjectPayload}} (below), marshalling of the object would occur late, and it would be marshalled directly into the output stream of the bundler, eliminating the byte[] array allocation made by the application.
h3. Design
Instead of copying, the application creates an instance of {{Payload}} and sets the payload in {{Message}}. The {{Payload}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of payload implementations, e.g.
* {{ByteArrayPayload}}: wraps a byte[] array with an offset and length
* {{NioDirectPayload}}: wraps an NIO direct {{ByteBuffer}}
* {{NioHeapPayload}}: wraps an NIO heap-based {{ByteBuffer}}
* {{CompositePayload}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
* {{IntPayload}}: a single integer
* {{ObjectPayload}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in payloads and they're only marshalled at the end (transport).
* {{PartialPayload}}: a ref to a {{Payload}}, with an offset and length
* {{InputStreamPayload}}: has a ref to an input stream and copies data from input- to output stream when marshalling
The {{Payload}} interface has methods:
* {{size()}}
* {{writeTo(DataOutput)}}
* {{readFrom(DataInput)}}
* {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying payload
and possibly also
* {{acquire()}} and
* {{release()}} (for ref-counting)
* {{copy()}}
Each payload impl has an ID and it should be possible to register new impls. A {{PayloadFactory}} maintains a mapping between IDs and impl classes.
When marshalling a {{Payload}}, the ID is written first, followed by the payload's {{writeTo()}} method. When reading payloads, the {{PayloadFactory}} is used to create instances from IDs.
h4. Fragmentation
When fragmenting a buffer, the fragments are instances of {{PartialPayload}} which maintains an offset and length over an underlying payload. When marshalling a {{PartialPayload}}, only the part between offset and offset+length is written to the output stream.
For fragmentation, method {{size()}} is crucial to determine whether a payload needs to be fragmented, or not. If, for example, a payload (e.g. an {{ObjectPayload}}) cannot determine the correct size, it may return {{-1}}. This leads to the {{ObjectPayload}} getting marshalled right away and getting wrapped into a {{ByteArrayPayload}}. So if {{size()}} cannot be determined, we have exactly the same behavior as what's currently done.
h4. Reference counting
If we implement ref-counting, then payloads can be reused as soon as the ref-count is 0. For example, when sending a message, the payload's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the payload cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the payload cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
h4. Payload factory
When a request is received, the buffer is created from the bytes received on the network, based on the ID. This should be done by asking a {{PayloadFactory}} component for a new buffer. A naive implementation might create a new buffer every time, and more sophisticated one might use a pool of payloads.
The {{PayloadFactory}} instance could be replaced by one's own implementation; this allows for an application to control the lifecycle of payloads: thus the creation of buffers by the application and of payloads received over the network can be controlled by the same payload management impl.
h4. Symmetry
When sending a {{CompositePayload}} of a 500 byte {{ByteArrayPayload}} and a 1000 byte {{NioDirectPayload}}, would we want to also get the same {{CompositePayload}} consisting of 2 payloads on the receiver side, or would we want to combine the 2 payloads into one and make the 2 payloads refer to the same combined byte[] array (or NIO buffer)? Should this be made configurable?
h4. ObjectPayload
If ObjectPayload cannot determine the size of the serialized data, it should return {{-1}}. This means that {{Message.setPayload(ObjectPayload)}} would right away serialize {{ObjectPayload}} into {{ByteArrayPayload}}.
This means we do have the {{byte[]}} array creation (same as now), but for object payloads which do implement {{size()}} correctly, we could still do late serialization.
h5. ObjectPayload and fragmentation
{{FRAG3}} could decorate {{ObjectPayload}} with a fragmentation payload, which generates fragments on serialization and sends them down the stack.
h4. Misc
* Since this issue includes API changes, the version will be 5.0
> New payload interface
> ---------------------
>
> Key: JGRP-2218
> URL: https://issues.jboss.org/browse/JGRP-2218
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 5.0
>
>
> h3. Goal
> Change payload in {{Message}} from byte[] arrays to a {{Payload}} interface which can have multiple implementations.
> h3. Reason
> Currently, having to pass a byte[] array to a message leads to unnecessary copying:
> * When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
> * When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
> * When an object has to be sent (e.g. in Infinispan), the object has to be marshalled into a byte[] array (first allocation) and then added to the message. With the suggested {{ObjectPayload}} (below), marshalling of the object would occur late, and it would be marshalled directly into the output stream of the bundler, eliminating the byte[] array allocation made by the application.
> h3. Design
> Instead of copying, the application creates an instance of {{Payload}} and sets the payload in {{Message}}. The {{Payload}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of payload implementations, e.g.
> * {{ByteArrayPayload}}: wraps a byte[] array with an offset and length
> * {{NioDirectPayload}}: wraps an NIO direct {{ByteBuffer}}
> * {{NioHeapPayload}}: wraps an NIO heap-based {{ByteBuffer}}
> * {{CompositePayload}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
> * {{IntPayload}}: a single integer
> * {{ObjectPayload}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in payloads and they're only marshalled at the end (transport).
> * {{PartialPayload}}: a ref to a {{Payload}}, with an offset and length
> * {{InputStreamPayload}}: has a ref to an input stream and copies data from input- to output stream when marshalling
> The {{Payload}} interface has methods:
> * {{size()}}
> * {{writeTo(DataOutput)}}
> * {{readFrom(DataInput)}}
> * {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying payload
> and possibly also
> * {{acquire()}} and
> * {{release()}} (for ref-counting)
> * {{copy()}}
> Each payload impl has an ID and it should be possible to register new impls. A {{PayloadFactory}} maintains a mapping between IDs and impl classes.
> When marshalling a {{Payload}}, the ID is written first, followed by the payload's {{writeTo()}} method. When reading payloads, the {{PayloadFactory}} is used to create instances from IDs.
> h4. Fragmentation
> When fragmenting a buffer, the fragments are instances of {{PartialPayload}} which maintains an offset and length over an underlying payload. When marshalling a {{PartialPayload}}, only the part between offset and offset+length is written to the output stream.
> For fragmentation, method {{size()}} is crucial to determine whether a payload needs to be fragmented, or not. If, for example, a payload (e.g. an {{ObjectPayload}}) cannot determine the correct size, it may return {{-1}}. This leads to the {{ObjectPayload}} getting marshalled right away and getting wrapped into a {{ByteArrayPayload}}. So if {{size()}} cannot be determined, we have exactly the same behavior as what's currently done.
> h4. Reference counting
> If we implement ref-counting, then payloads can be reused as soon as the ref-count is 0. For example, when sending a message, the payload's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the payload cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the payload cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
> h4. Payload factory
> When a request is received, the buffer is created from the bytes received on the network, based on the ID. This should be done by asking a {{PayloadFactory}} component for a new buffer. A naive implementation might create a new buffer every time, but a more sophisticated one might use a pool of payloads.
> The {{PayloadFactory}} instance could be replaced by one's own implementation; this allows for an application to control the lifecycle of payloads: thus the creation of buffers by the application and of payloads received over the network can be controlled by the same payload management impl.
> h4. Symmetry
> When sending a {{CompositePayload}} of a 500 byte {{ByteArrayPayload}} and a 1000 byte {{NioDirectPayload}}, would we want to also get the same {{CompositePayload}} consisting of 2 payloads on the receiver side, or would we want to combine the 2 payloads into one and make the 2 payloads refer to the same combined byte[] array (or NIO buffer)? Should this be made configurable?
> h4. ObjectPayload
> If ObjectPayload cannot determine the size of the serialized data, it should return {{-1}}. This means that {{Message.setPayload(ObjectPayload)}} would right away serialize {{ObjectPayload}} into {{ByteArrayPayload}}.
> This means we do have the {{byte[]}} array creation (same as now), but for object payloads which do implement {{size()}} correctly, we could still do late serialization.
> h5. ObjectPayload and fragmentation
> {{FRAG3}} could decorate {{ObjectPayload}} with a fragmentation payload, which generates fragments on serialization and sends them down the stack.
> h4. Misc
> * Since this issue includes API changes, the version will be 5.0
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months
[JBoss JIRA] (JGRP-2218) New payload interface
by Bela Ban (JIRA)
[ https://issues.jboss.org/browse/JGRP-2218?page=com.atlassian.jira.plugin.... ]
Bela Ban updated JGRP-2218:
---------------------------
Description:
h3. Goal
Change payload in {{Message}} from byte[] arrays to a {{Payload}} interface which can have multiple implementations.
h3. Reason
Currently, having to pass a byte[] array to a message leads to unnecessary copying:
* When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
* When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
* When an object has to be sent (e.g. in Infinispan), the object has to be marshalled into a byte[] array (first allocation) and then added to the message. With the suggested {{ObjectPayload}} (below), marshalling of the object would occur late, and it would be marshalled directly into the output stream of the bundler, eliminating the byte[] array allocation made by the application.
h3. Design
Instead of copying, the application creates an instance of {{Payload}} and sets the payload in {{Message}}. The {{Payload}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of payload implementations, e.g.
* {{ByteArrayPayload}}: wraps a byte[] array with an offset and length
* {{NioDirectPayload}}: wraps an NIO direct {{ByteBuffer}}
* {{NioHeapPayload}}: wraps an NIO heap-based {{ByteBuffer}}
* {{CompositePayload}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
* {{IntPayload}}: a single integer
* {{ObjectPayload}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in payloads and they're only marshalled at the end (transport).
* {{PartialPayload}}: a ref to a {{Payload}}, with an offset and length
* {{InputStreamPayload}}: has a ref to an input stream and copies data from input- to output stream when marshalling
The {{Payload}} interface has methods:
* {{size()}}
* {{writeTo(DataOutput)}}
* {{readFrom(DataInput)}}
* {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying payload
and possibly also
* {{acquire()}} and
* {{release()}} (for ref-counting)
* {{copy()}}
Each payload impl has an ID and it should be possible to register new impls. A {{PayloadFactory}} maintains a mapping between IDs and impl classes.
When marshalling a {{Payload}}, the ID is written first, followed by the payload's {{writeTo()}} method. When reading payloads, the {{PayloadFactory}} is used to create instances from IDs.
h4. Fragmentation
When fragmenting a buffer, the fragments are instances of {{PartialPayload}} which maintains an offset and length over an underlying payload. When marshalling a {{PartialPayload}}, only the part between offset and offset+length is written to the output stream.
For fragmentation, method {{size()}} is crucial to determine whether a payload needs to be fragmented, or not. If, for example, a payload (e.g. an {{ObjectPayload}}) cannot determine the correct size, it may return {{-1}}. This leads to the {{ObjectPayload}} getting marshalled right away and getting wrapped into a {{ByteArrayPayload}}. So if {{size()}} cannot be determined, we have exactly the same behavior as what's currently done.
h4. Reference counting
If we implement ref-counting, then payloads can be reused as soon as the ref-count is 0. For example, when sending a message, the payload's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the payload cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the payload cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
h4. Payload factory
When a request is received, the buffer is created from the bytes received on the network, based on the ID. This should be done by asking a {{PayloadFactory}} component for a new buffer. A naive implementation might create a new buffer every time, and more sophisticated one might use a pool of payloads.
The {{PayloadFactory}} instance could be replaced by one's own implementation; this allows for an application to control the lifecycle of payloads: thus the creation of buffers by the application and of payloads received over the network can be controlled by the same payload management impl.
h4. Symmetry
When sending a {{CompositePayload}} of a 500 byte {{ByteArrayPayload}} and a 1000 byte {{NioDirectPayload}}, would we want to also get the same {{CompositePayload}} consisting of 2 payloads on the receiver side, or would we want to combine the 2 payloads into one and make the 2 payloads refer to the same combined byte[] array (or NIO buffer)? Should this be made configurable?
h4. ObjectPayload
If ObjectPayload cannot determine the size of the serialized data, it should return {{-1}}. This means that {{Message.setPayload(ObjectPayload)}} would right away serialize {{ObjectPayload}} into {{ByteArrayPayload}}.
This means we do have the {{byte[]}} array creation (same as now), but for object payloads which do implement {{size()}} correctly, we could still do late serialization.
h5. ObjectPayload and fragmentation
{{FRAG3}} could decorate {{ObjectPayload}} with a fragmentation payload, which generates fragments on serialization and sends them down the stack.
h4. Misc
* Since this issue includes API changes, the version will be 5.0
was:
h3. Goal
Change payload in {{Message}} from byte[] arrays to a {{Payload}} interface which can have multiple implementations.
h3. Reason
Currently, having to pass a byte[] array to a message leads to unnecessary copying:
* When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
* When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
* When an object has to be sent (e.g. in Infinispan), the object has to be marshalled into a byte[] array (first allocation) and then added to the message. With the suggested {{ObjectPayload}} (below), marshalling of the object would occur late, and it would be marshalled directly into the output stream of the bundler, eliminating the byte[] array allocation made by the application.
h3. Design
Instead of copying, the application creates an instance of {{Payload}} and sets the payload in {{Message}}. The {{Payload}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of payload implementations, e.g.
* {{ByteArrayPayload}}: wraps a byte[] array with an offset and length
* {{NioDirectPayload}}: wraps an NIO direct {{ByteBuffer}}
* {{NioHeapPayload}}: wraps an NIO heap-based {{ByteBuffer}}
* {{CompositePayload}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
* {{IntPayload}}: a single integer
* {{ObjectPayload}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in payloads and they're only marshalled at the end (transport).
* {{PartialPayload}}: a ref to a {{Payload}}, with an offset and length
* {{InputStreamPayload}}: has a ref to an input stream and copies data from input- to output stream when marshalling
The {{Payload}} interface has methods:
* {{size()}}
* {{writeTo(DataOutput)}}
* {{readFrom(DataInput)}}
* {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying payload
and possibly also
* {{acquire()}} and
* {{release()}} (for ref-counting)
* {{copy()}}
Each payload impl has an ID and it should be possible to register new impls. A {{PayloadFactory}} maintains a mapping between IDs and impl classes.
When marshalling a {{Payload}}, the ID is written first, followed by the payload's {{writeTo()}} method. When reading payloads, the {{PayloadFactory}} is used to create instances from IDs.
h4. Fragmentation
When fragmenting a buffer, the fragments are instances of {{PartialPayload}} which maintains an offset and length over an underlying payload. When marshalling a {{PartialPayload}}, only the part between offset and offset+length is written to the output stream.
h4. Reference counting
If we implement ref-counting, then payloads can be reused as soon as the ref-count is 0. For example, when sending a message, the payload's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the payload cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the payload cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
h4. Payload factory
When a request is received, the buffer is created from the bytes received on the network, based on the ID. This should be done by asking a {{PayloadFactory}} component for a new buffer. A naive implementation might create a new buffer every time, and more sophisticated one might use a pool of payloads.
The {{PayloadFactory}} instance could be replaced by one's own implementation; this allows for an application to control the lifecycle of payloads: thus the creation of buffers by the application and of payloads received over the network can be controlled by the same payload management impl.
h4. Symmetry
When sending a {{CompositePayload}} of a 500 byte {{ByteArrayPayload}} and a 1000 byte {{NioDirectPayload}}, would we want to also get the same {{CompositePayload}} consisting of 2 payloads on the receiver side, or would we want to combine the 2 payloads into one and make the 2 payloads refer to the same combined byte[] array (or NIO buffer)? Should this be made configurable?
h4. ObjectPayload
If ObjectPayload cannot determine the size of the serialized data, it should return {{-1}}. This means that {{Message.setPayload(ObjectPayload)}} would right away serialize {{ObjectPayload}} into {{ByteArrayPayload}}.
This means we do have the {{byte[]}} array creation (same as now), but for object payloads which do implement {{size()}} correctly, we could still do late serialization.
h5. ObjectPayload and fragmentation
{{FRAG3}} could decorate {{ObjectPayload}} with a fragmentation payload, which generates fragments on serialization and sends them down the stack.
h4. Misc
* Since this issue includes API changes, the version will be 5.0
> New payload interface
> ---------------------
>
> Key: JGRP-2218
> URL: https://issues.jboss.org/browse/JGRP-2218
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 5.0
>
>
> h3. Goal
> Change payload in {{Message}} from byte[] arrays to a {{Payload}} interface which can have multiple implementations.
> h3. Reason
> Currently, having to pass a byte[] array to a message leads to unnecessary copying:
> * When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
> * When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
> * When an object has to be sent (e.g. in Infinispan), the object has to be marshalled into a byte[] array (first allocation) and then added to the message. With the suggested {{ObjectPayload}} (below), marshalling of the object would occur late, and it would be marshalled directly into the output stream of the bundler, eliminating the byte[] array allocation made by the application.
> h3. Design
> Instead of copying, the application creates an instance of {{Payload}} and sets the payload in {{Message}}. The {{Payload}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of payload implementations, e.g.
> * {{ByteArrayPayload}}: wraps a byte[] array with an offset and length
> * {{NioDirectPayload}}: wraps an NIO direct {{ByteBuffer}}
> * {{NioHeapPayload}}: wraps an NIO heap-based {{ByteBuffer}}
> * {{CompositePayload}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
> * {{IntPayload}}: a single integer
> * {{ObjectPayload}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in payloads and they're only marshalled at the end (transport).
> * {{PartialPayload}}: a ref to a {{Payload}}, with an offset and length
> * {{InputStreamPayload}}: has a ref to an input stream and copies data from input- to output stream when marshalling
> The {{Payload}} interface has methods:
> * {{size()}}
> * {{writeTo(DataOutput)}}
> * {{readFrom(DataInput)}}
> * {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying payload
> and possibly also
> * {{acquire()}} and
> * {{release()}} (for ref-counting)
> * {{copy()}}
> Each payload impl has an ID and it should be possible to register new impls. A {{PayloadFactory}} maintains a mapping between IDs and impl classes.
> When marshalling a {{Payload}}, the ID is written first, followed by the payload's {{writeTo()}} method. When reading payloads, the {{PayloadFactory}} is used to create instances from IDs.
> h4. Fragmentation
> When fragmenting a buffer, the fragments are instances of {{PartialPayload}} which maintains an offset and length over an underlying payload. When marshalling a {{PartialPayload}}, only the part between offset and offset+length is written to the output stream.
> For fragmentation, method {{size()}} is crucial to determine whether a payload needs to be fragmented, or not. If, for example, a payload (e.g. an {{ObjectPayload}}) cannot determine the correct size, it may return {{-1}}. This leads to the {{ObjectPayload}} getting marshalled right away and getting wrapped into a {{ByteArrayPayload}}. So if {{size()}} cannot be determined, we have exactly the same behavior as what's currently done.
> h4. Reference counting
> If we implement ref-counting, then payloads can be reused as soon as the ref-count is 0. For example, when sending a message, the payload's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the payload cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the payload cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
> h4. Payload factory
> When a request is received, the buffer is created from the bytes received on the network, based on the ID. This should be done by asking a {{PayloadFactory}} component for a new buffer. A naive implementation might create a new buffer every time, and more sophisticated one might use a pool of payloads.
> The {{PayloadFactory}} instance could be replaced by one's own implementation; this allows for an application to control the lifecycle of payloads: thus the creation of buffers by the application and of payloads received over the network can be controlled by the same payload management impl.
> h4. Symmetry
> When sending a {{CompositePayload}} of a 500 byte {{ByteArrayPayload}} and a 1000 byte {{NioDirectPayload}}, would we want to also get the same {{CompositePayload}} consisting of 2 payloads on the receiver side, or would we want to combine the 2 payloads into one and make the 2 payloads refer to the same combined byte[] array (or NIO buffer)? Should this be made configurable?
> h4. ObjectPayload
> If ObjectPayload cannot determine the size of the serialized data, it should return {{-1}}. This means that {{Message.setPayload(ObjectPayload)}} would right away serialize {{ObjectPayload}} into {{ByteArrayPayload}}.
> This means we do have the {{byte[]}} array creation (same as now), but for object payloads which do implement {{size()}} correctly, we could still do late serialization.
> h5. ObjectPayload and fragmentation
> {{FRAG3}} could decorate {{ObjectPayload}} with a fragmentation payload, which generates fragments on serialization and sends them down the stack.
> h4. Misc
> * Since this issue includes API changes, the version will be 5.0
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 6 months