Big transfer and Write traffic shaping issues fixed

Motivation:
Several issues were shown by various ticket (#2900 #2956).
Also use the improvement on writability user management from #3036.

Issue #2900
When a huge amount of data are written, the current behavior of the
TrafficShaping handler is to limit the delay to 15s, whatever the delay
the previous write has. This is wrong, and when a huge amount of writes
are done in a short time, the traffic is not correctly shapened.

Moreover, there is a high risk of OOM if one is not using in his/her own
handler for instance ChannelFuture.addListener() to handle the write
bufferisation in the TrafficShapingHandler.

This fix use the "user-defined writability flags" from #3036 to
allow the TrafficShapingHandlers to "user-defined" managed writability directly, as
for reading, thus using the default isWritable() and
channelWritabilityChanged().
This allows for instance HttpChunkedInput to be fully compatible.

The "bandwidth" compute on write is only on "acquired" write orders, not
on "real" write orders, which is wrong from statistic point of view.

Issue #2956
When using GlobalTrafficShaping, every write (and read) are
synchronized, thus leading to a drop of performance.
ChannelTrafficShaping is not touched by this issue since synchronized is
then correct (handler is per channel, so the synchronized).

Modifications:
The current write delay computation takes into account the previous
write delay and time to check is the 15s delay (maxTime) is really
exceeded or not (using last scheduled write time). The algorithm is
simplified and in the same time more accurate.

This proposal uses the #3036 improvement on user-defined writability flags.

When the real write occurs, the statistics are update accordingly on a
new attribute (getRealWriteThroughput()).

To limit the synchronisations, all synchronized on
GlobalTrafficShapingHandler on submitWrite were removed. They are
replaced with a lock per channel (since synchronization is still needed
to prevent unordered write per channel), as in the sendAllValid method
for the very same reason.
Also all synchronized on TrafficCounter on read/writeTimeToWait() are
removed as they are unnecessary since already locked before by the
caller.
Still the creation and remove operations on lock per channel (PerChannel
object) are synchronized to prevent concurrency issue on this critical
part, but then limited.

Result:
The traffic shaping is more stable, even with a huge number of writes in
short time by taking into consideration last scheduled write time.

The current implementation of TrafficShapingHandler using user-defined writability flags
and default isWritable() and fireChannelWritabilityChanged works as expected.

The statistics are more valuable (asked write vs real write).

Various examples are shown in one added example (example/traffic), and
in particular how a user handler might managed the write to prevent OOM:

- using the ChannelFuture.addListener(new GenericFutureListener>() one by one, or by set of writes
- using the ctx.channel().isWritable() and channelWritabilityChanged()
- using a code as HttpChunkedInput to send the chunks according to the channelWritabilityChanged() (softWritability is needed)
- using no specific check, but with the risk of OOM (no control on the bufferisation made by the TSH)

The Global TrafficShapingHandler should now have less "global"
synchronization, hoping to the minimum, but still per Channel as needed.

I understand your concern. I have some case study where the "attributes" of the Traffic Shaping could changes from time to time, but rarely enough to not impose volatile, but to impose not to be final.

One use case is for instance the change between day and night hours. I agree already what you could reply is that it applies mainly on traffic shaping itself (bandwidth), not memory consumption. However we could imagine that during days, a lot of programs are running, therefore having less memory for this Java process, and reversely during night. So system property is not the solution too there.

Adding to the constructor changes potentially the interface but surely and mainly with some difficulty to manage a constructor with 0, 1, 2, 3 or 4 long values, now adding a 5th long value. Currently those values are comprehensible, but each could be changed dynamically.

However there are not supposed to be changed too frequently (maybe the java doc should be clear on that), even if we put volatile, since the bandwidth will only be computed for "next" packets, not the already received/sent ones. For instance, if for some reasons, the traffic shaping planned 1 minute ahead of traffic in the list or in the readable property, changing the traffic shaping by, for instance, opening full traffic, will take place after this 1 minute, as best effort (to prevent too much computations and too complicated computations).

I could change them to volatile, but at the price of read/write access (barrier implicit through volatile) while not mandatory.

I agree however that some of these properties shall not be changed often (as the memory limit or the timeout limit), but not enabling those changes could have some particular effect on specific needs. One option could be to change those property setters to be "protected" such that one could change the value by explicitely making a public method in a extended version, but why not proposing it immediately at first, putting however more documentation on that?

Tell me what is your feeiling, I'm sure you're far better than me on that, so that I will follow your advice ;-)