Buffers a durable atomic increment for coalescing. This increment will be held in memory up to the amount of time allowed by #getFlushInterval in order to allow the client to coalesce increments. Increment coalescing can dramatically reduce the number of RPCs and write load on HBase
(final AtomicIncrementRequest request)
| 1681 | * @since 1.4 This method works with negative increment values. |
| 1682 | */ |
| 1683 | public Deferred<Long> bufferAtomicIncrement(final AtomicIncrementRequest request) { |
| 1684 | final long value = request.getAmount(); |
| 1685 | if (!BufferedIncrement.Amount.checkOverflow(value) // Value too large. |
| 1686 | || flush_interval == 0) { // Client-side buffer disabled. |
| 1687 | return atomicIncrement(request); |
| 1688 | } |
| 1689 | |
| 1690 | final BufferedIncrement incr = |
| 1691 | new BufferedIncrement(request.table(), request.key(), request.family(), |
| 1692 | request.qualifier()); |
| 1693 | |
| 1694 | do { |
| 1695 | BufferedIncrement.Amount amount; |
| 1696 | // Semi-evil: the very first time we get here, `increment_buffer' will |
| 1697 | // still be null (we don't initialize it in our constructor) so we catch |
| 1698 | // the NPE that ensues to allocate the buffer and kick off a timer to |
| 1699 | // regularly flush it. |
| 1700 | try { |
| 1701 | amount = increment_buffer.getUnchecked(incr); |
| 1702 | } catch (NullPointerException e) { |
| 1703 | setupIncrementCoalescing(); |
| 1704 | amount = increment_buffer.getUnchecked(incr); |
| 1705 | } |
| 1706 | if (amount.update(value)) { |
| 1707 | final Deferred<Long> deferred = new Deferred<Long>(); |
| 1708 | amount.deferred.chain(deferred); |
| 1709 | return deferred; |
| 1710 | } |
| 1711 | // else: Loop again to retry. |
| 1712 | increment_buffer.refresh(incr); |
| 1713 | } while (true); |
| 1714 | } |
| 1715 | |
| 1716 | /** |
| 1717 | * Buffers a durable atomic increment for coalescing. |