1 /** @file
2 
3   I/O classes
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22 
23   @section watermark Watermark
24 
25   Watermarks can be used as an interface between the data transferring
26   layer (VConnection) and the user layer (a state machine).  Watermarks
27   should be used when you need to have at least a certain amount of data
28   to make some determination.  For example, when parsing a string, one
29   might wish to ensure that an entire line will come in before consuming
30   the data.  In such a case, the water_mark should be set to the largest
31   possible size of the string. (appropriate error handling should take
32   care of excessively long strings).
33 
34   In all other cases, especially when all data will be consumed, the
35   water_mark should be set to 0 (the default).
36 
37  */
38 
39 #pragma once
40 #define I_IOBuffer_h
41 
42 #include "tscore/ink_platform.h"
43 #include "tscore/ink_apidefs.h"
44 #include "tscore/Allocator.h"
45 #include "tscore/Ptr.h"
46 #include "tscore/ink_assert.h"
47 #include "tscore/ink_resource.h"
48 
49 struct MIOBufferAccessor;
50 
51 class MIOBuffer;
52 class IOBufferReader;
53 class VIO;
54 
55 inkcoreapi extern int64_t max_iobuffer_size;
56 extern int64_t default_small_iobuffer_size;
57 extern int64_t default_large_iobuffer_size; // matched to size of OS buffers
58 
59 #if !defined(TRACK_BUFFER_USER)
60 #define TRACK_BUFFER_USER 1
61 #endif
62 
63 enum AllocType {
64   NO_ALLOC,
65   FAST_ALLOCATED,
66   XMALLOCED,
67   MEMALIGNED,
68   DEFAULT_ALLOC,
69   CONSTANT,
70 };
71 
72 #define DEFAULT_BUFFER_NUMBER 128
73 #define DEFAULT_HUGE_BUFFER_NUMBER 32
74 #define MAX_MIOBUFFER_READERS 5
75 #define DEFAULT_BUFFER_ALIGNMENT 8192 // should be disk/page size
76 #define DEFAULT_BUFFER_BASE_SIZE 128
77 
78 ////////////////////////////////////////////////
79 // These are defines so that code that used 2 //
80 // for buffer size index when 2 was 2K will   //
81 // still work if it uses BUFFER_SIZE_INDEX_2K //
82 // instead.                                   //
83 ////////////////////////////////////////////////
84 #define BUFFER_SIZE_INDEX_128 0
85 #define BUFFER_SIZE_INDEX_256 1
86 #define BUFFER_SIZE_INDEX_512 2
87 #define BUFFER_SIZE_INDEX_1K 3
88 #define BUFFER_SIZE_INDEX_2K 4
89 #define BUFFER_SIZE_INDEX_4K 5
90 #define BUFFER_SIZE_INDEX_8K 6
91 #define BUFFER_SIZE_INDEX_16K 7
92 #define BUFFER_SIZE_INDEX_32K 8
93 #define BUFFER_SIZE_INDEX_64K 9
94 #define BUFFER_SIZE_INDEX_128K 10
95 #define BUFFER_SIZE_INDEX_256K 11
96 #define BUFFER_SIZE_INDEX_512K 12
97 #define BUFFER_SIZE_INDEX_1M 13
98 #define BUFFER_SIZE_INDEX_2M 14
99 #define MAX_BUFFER_SIZE_INDEX 14
100 #define DEFAULT_BUFFER_SIZES (MAX_BUFFER_SIZE_INDEX + 1)
101 
102 #define BUFFER_SIZE_FOR_INDEX(_i) (DEFAULT_BUFFER_BASE_SIZE * (1 << (_i)))
103 #define DEFAULT_SMALL_BUFFER_SIZE BUFFER_SIZE_INDEX_512
104 #define DEFAULT_LARGE_BUFFER_SIZE BUFFER_SIZE_INDEX_4K
105 #define DEFAULT_TS_BUFFER_SIZE BUFFER_SIZE_INDEX_8K
106 #define DEFAULT_MAX_BUFFER_SIZE BUFFER_SIZE_FOR_INDEX(MAX_BUFFER_SIZE_INDEX)
107 #define MIN_IOBUFFER_SIZE BUFFER_SIZE_INDEX_128
108 #define MAX_IOBUFFER_SIZE (DEFAULT_BUFFER_SIZES - 1)
109 
110 #define BUFFER_SIZE_ALLOCATED(_i) (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_i) || BUFFER_SIZE_INDEX_IS_XMALLOCED(_i))
111 
112 #define BUFFER_SIZE_NOT_ALLOCATED DEFAULT_BUFFER_SIZES
113 #define BUFFER_SIZE_INDEX_IS_XMALLOCED(_size_index) (_size_index < 0)
114 #define BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_size_index) (((uint64_t)_size_index) < DEFAULT_BUFFER_SIZES)
115 #define BUFFER_SIZE_INDEX_IS_CONSTANT(_size_index) (_size_index >= DEFAULT_BUFFER_SIZES)
116 
117 #define BUFFER_SIZE_FOR_XMALLOC(_size) (-(_size))
118 #define BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(_size) (-(_size))
119 
120 #define BUFFER_SIZE_FOR_CONSTANT(_size) (_size - DEFAULT_BUFFER_SIZES)
121 #define BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(_size) (_size + DEFAULT_BUFFER_SIZES)
122 
123 inkcoreapi extern Allocator ioBufAllocator[DEFAULT_BUFFER_SIZES];
124 
125 void init_buffer_allocators(int iobuffer_advice);
126 
127 /**
128   A reference counted wrapper around fast allocated or malloced memory.
129   The IOBufferData class provides two basic services around a portion
130   of allocated memory.
131 
132   First, it is a reference counted object and ...
133 
134   @remarks The AllocType enum, is used to define the type of allocation
135   for the memory this IOBufferData object manages.
136 
137   <table>
138     <tr>
139       <td align="center">AllocType</td>
140       <td align="center">Meaning</td>
141     </tr>
142     <tr>
143       <td>NO_ALLOC</td>
144       <td></td>
145     </tr>
146     <tr>
147       <td>FAST_ALLOCATED</td>
148       <td></td>
149     </tr>
150     <tr>
151       <td>XMALLOCED</td>
152       <td></td>
153     </tr>
154     <tr>
155       <td>MEMALIGNED</td>
156       <td></td>
157     </tr>
158     <tr>
159       <td>DEFAULT_ALLOC</td>
160       <td></td>
161     </tr>
162     <tr>
163       <td>CONSTANT</td>
164       <td></td>
165     </tr>
166   </table>
167 
168  */
169 class IOBufferData : public RefCountObj
170 {
171 public:
172   /**
173     The size of the memory allocated by this IOBufferData. Calculates
174     the amount of memory allocated by this IOBufferData.
175 
176     @return number of bytes allocated for the '_data' member.
177 
178   */
179   int64_t block_size();
180 
181   /**
182     Frees the memory managed by this IOBufferData.  Deallocates the
183     memory previously allocated by this IOBufferData object. It frees
184     the memory pointed to by '_data' according to the '_mem_type' and
185     '_size_index' members.
186 
187   */
188   void dealloc();
189 
190   /**
191     Allocates memory and sets this IOBufferData to point to it.
192     Allocates memory according to the size_index and type
193     parameters. Any previously allocated memory pointed to by
194     this IOBufferData is deallocated.
195 
196     @param size_index
197     @param type of allocation to use; see remarks section.
198   */
199   void alloc(int64_t size_index, AllocType type = DEFAULT_ALLOC);
200 
201   /**
202     Provides access to the allocated memory. Returns the address of the
203     allocated memory handled by this IOBufferData.
204 
205     @return address of the memory handled by this IOBufferData.
206 
207   */
208   char *
209   data()
210   {
211     return _data;
212   }
213 
214   /**
215     Cast operator. Provided as a convenience, the cast to a char* applied
216     to the IOBufferData returns the address of the memory handled by the
217     IOBuffer data. In this manner, objects of this class can be used as
218     parameter to functions requiring a char*.
219 
220   */
221   operator char *() { return _data; }
222   /**
223     Frees the IOBufferData object and its underlying memory. Deallocates
224     the memory managed by this IOBufferData and then frees itself. You
225     should not use this object or reference after this call.
226 
227   */
228   void free() override;
229 
230   int64_t _size_index;
231 
232   /**
233     Type of allocation used for the managed memory. Stores the type of
234     allocation used for the memory currently managed by the IOBufferData
235     object. Do not set or modify this value directly. Instead use the
236     alloc or dealloc methods.
237 
238   */
239   AllocType _mem_type = NO_ALLOC;
240 
241   /**
242     Points to the allocated memory. This member stores the address of
243     the allocated memory. You should not modify its value directly,
244     instead use the alloc or dealloc methods.
245 
246   */
247   char *_data = nullptr;
248 
249 #ifdef TRACK_BUFFER_USER
250   const char *_location = nullptr;
251 #endif
252 
253   /**
254     Constructor. Initializes state for a IOBufferData object. Do not use
255     this method. Use one of the functions with the 'new_' prefix instead.
256 
257   */
258   IOBufferData() : _size_index(BUFFER_SIZE_NOT_ALLOCATED) {}
259 
260   // noncopyable, declaration only
261   IOBufferData(const IOBufferData &) = delete;
262   IOBufferData &operator=(const IOBufferData &) = delete;
263 };
264 
265 inkcoreapi extern ClassAllocator<IOBufferData> ioDataAllocator;
266 
267 /**
268   A linkable portion of IOBufferData. IOBufferBlock is a chainable
269   buffer block descriptor. The IOBufferBlock represents both the used
270   and available space in the underlying block. The IOBufferBlock is not
271   sharable between buffers but rather represents what part of the data
272   block is both in use and usable by the MIOBuffer it is attached to.
273 
274 */
275 class IOBufferBlock : public RefCountObj
276 {
277 public:
278   /**
279     Access the actual data. Provides access to rhe underlying data
280     managed by the IOBufferData.
281 
282     @return pointer to the underlying data.
283 
284   */
285   char *
286   buf()
287   {
288     return data->_data;
289   }
290 
291   /**
292     Beginning of the inuse section. Returns the position in the buffer
293     where the inuse area begins.
294 
295     @return pointer to the start of the inuse section.
296 
297   */
298   char *
299   start()
300   {
301     return _start;
302   }
303 
304   /**
305     End of the used space. Returns a pointer to end of the used space
306     in the data buffer represented by this block.
307 
308     @return pointer to the end of the inuse portion of the block.
309 
310   */
311   char *
312   end()
313   {
314     return _end;
315   }
316 
317   /**
318     End of the data buffer. Returns a pointer to end of the data buffer
319     represented by this block.
320 
321   */
322   char *
323   buf_end()
324   {
325     return _buf_end;
326   }
327 
328   /**
329     Size of the inuse area. Returns the size of the current inuse area.
330 
331     @return bytes occupied by the inuse area.
332 
333   */
334   int64_t
335   size()
336   {
337     return (int64_t)(_end - _start);
338   }
339 
340   /**
341     Size of the data available for reading. Returns the size of the data
342     available for reading in the inuse area.
343 
344     @return bytes available for reading from the inuse area.
345 
346   */
347   int64_t
348   read_avail() const
349   {
350     return (int64_t)(_end - _start);
351   }
352 
353   /**
354     Space available in the buffer. Returns the number of bytes that can
355     be written to the data buffer.
356 
357     @return space available for writing in this IOBufferBlock.
358   */
359   int64_t
360   write_avail()
361   {
362     return (int64_t)(_buf_end - _end);
363   }
364 
365   /**
366     Size of the memory allocated by the underlying IOBufferData.
367     Computes the size of the entire block, which includes the used and
368     available areas. It is the memory allocated by the IOBufferData
369     referenced by this IOBufferBlock.
370 
371     @return bytes allocated to the IOBufferData referenced by this
372       IOBufferBlock.
373 
374   */
375   int64_t
376   block_size()
377   {
378     return data->block_size();
379   }
380 
381   /**
382     Decrease the size of the inuse area. Moves forward the start of
383     the inuse area. This also decreases the number of available bytes
384     for reading.
385 
386     @param len bytes to consume or positions to skip for the start of
387       the inuse area.
388 
389   */
390   void consume(int64_t len);
391 
392   /**
393     Increase the inuse area of the block. Adds 'len' bytes to the inuse
394     area of the block. Data should be copied into the data buffer by
395     using end() to find the start of the free space in the data buffer
396     before calling fill()
397 
398     @param len bytes to increase the inuse area. It must be less than
399       or equal to the value of write_avail().
400 
401   */
402   void fill(int64_t len);
403 
404   /**
405     Reset the inuse area. The start and end of the inuse area are reset
406     but the actual IOBufferData referenced by this IOBufferBlock is not
407     modified.  This effectively reduces the number of bytes available
408     for reading to zero, and the number of bytes available for writing
409     to the size of the entire buffer.
410 
411   */
412   void reset();
413 
414   /**
415     Create a copy of the IOBufferBlock. Creates and returns a copy of this
416     IOBufferBlock that references the same data that this IOBufferBlock
417     (it does not allocate an another buffer). The cloned block will not
418     have a writable space since the original IOBufferBlock maintains the
419     ownership for writing data to the block.
420 
421     @return copy of this IOBufferBlock.
422 
423   */
424   IOBufferBlock *clone() const;
425 
426   /**
427     Clear the IOBufferData this IOBufferBlock handles. Clears this
428     IOBufferBlock's reference to the data buffer (IOBufferData). You can
429     use alloc after this call to allocate an IOBufferData associated to
430     this IOBufferBlock.
431 
432   */
433   void clear();
434 
435   /**
436     Allocate a data buffer. Allocates a data buffer for this IOBufferBlock
437     based on index 'i'.  Index values are described in the remarks
438     section in MIOBuffer.
439 
440   */
441   void alloc(int64_t i = default_large_iobuffer_size);
442 
443   /**
444     Clear the IOBufferData this IOBufferBlock handles. Clears this
445     IOBufferBlock's reference to the data buffer (IOBufferData).
446 
447   */
448   void dealloc();
449 
450   /**
451     Set or replace this IOBufferBlock's IOBufferData member. Sets this
452     IOBufferBlock's IOBufferData member to point to the IOBufferData
453     passed in. You can optionally specify the inuse area with the 'len'
454     argument and an offset for the start.
455 
456     @param d new IOBufferData this IOBufferBlock references.
457     @param len in use area to set. It must be less than or equal to the
458       length of the block size *IOBufferData).
459     @param offset bytes to skip from the beginning of the IOBufferData
460       and to mark its start.
461 
462   */
463   void set(IOBufferData *d, int64_t len = 0, int64_t offset = 0);
464   void set_internal(void *b, int64_t len, int64_t asize_index);
465   void realloc_set_internal(void *b, int64_t buf_size, int64_t asize_index);
466   void realloc(void *b, int64_t buf_size);
467   void realloc(int64_t i);
468   void realloc_xmalloc(void *b, int64_t buf_size);
469   void realloc_xmalloc(int64_t buf_size);
470 
471   /**
472     Frees the IOBufferBlock object and its underlying memory.
473     Removes the reference to the IOBufferData object and then frees
474     itself. You should not use this object or reference after this
475     call.
476 
477   */
478   void free() override;
479 
480   char *_start   = nullptr;
481   char *_end     = nullptr;
482   char *_buf_end = nullptr;
483 
484 #ifdef TRACK_BUFFER_USER
485   const char *_location = nullptr;
486 #endif
487 
488   /**
489     The underlying reference to the allocated memory. A reference to a
490     IOBufferData representing the memory allocated to this buffer. Do
491     not set or modify its value directly.
492 
493   */
494   Ptr<IOBufferData> data;
495 
496   /**
497     Reference to another IOBufferBlock. A reference to another
498     IOBufferBlock that allows this object to link to other.
499 
500   */
501   Ptr<IOBufferBlock> next;
502 
503   /**
504     Constructor of a IOBufferBlock. Do not use it to create a new object,
505     instead call new_IOBufferBlock
506 
507   */
508   IOBufferBlock();
509 
510   // noncopyable
511   IOBufferBlock(const IOBufferBlock &) = delete;
512   IOBufferBlock &operator=(const IOBufferBlock &) = delete;
513 };
514 
515 extern inkcoreapi ClassAllocator<IOBufferBlock> ioBlockAllocator;
516 
517 /** A class for holding a chain of IO buffer blocks.
518     This class is intended to be used as a member variable for other classes that
519     need to anchor an IO Buffer chain but don't need the full @c MIOBuffer machinery.
520     That is, the owner is the only reader/writer of the data.
521 
522     This does not handle incremental reads or writes well. The intent is that data is
523     placed in the instance, held for a while, then used and discarded.
524 
525     @note Contrast also with @c IOBufferReader which is similar but requires an
526     @c MIOBuffer as its owner.
527 */
528 class IOBufferChain
529 {
530   using self_type = IOBufferChain; ///< Self reference type.
531 
532 public:
533   /// Default constructor - construct empty chain.
534   IOBufferChain() = default;
535   /// Shallow copy.
536   self_type &operator=(self_type const &that);
537 
538   /// Shallow append.
539   self_type &operator+=(self_type const &that);
540 
541   /// Number of bytes of content.
542   int64_t length() const;
543 
544   /// Copy a chain of @a blocks in to this object up to @a length bytes.
545   /// If @a offset is greater than 0 that many bytes are skipped. Those bytes do not count
546   /// as part of @a length.
547   /// This creates a new chain using existing data blocks. This
548   /// breaks the original chain so that changes there (such as appending blocks)
549   /// is not reflected in this chain.
550   /// @return The number of bytes written to the chain.
551   int64_t write(IOBufferBlock *blocks, int64_t length, int64_t offset = 0);
552 
553   /// Add the content of a buffer block.
554   /// The buffer block is unchanged.
555   int64_t write(IOBufferData *data, int64_t length = 0, int64_t offset = 0);
556 
557   /// Remove @a size bytes of content from the front of the chain.
558   /// @return The actual number of bytes removed.
559   int64_t consume(int64_t size);
560 
561   /// Clear current chain.
562   void clear();
563 
564   /// Get the first block.
565   IOBufferBlock *head();
566   IOBufferBlock const *head() const;
567 
568   /// STL Container support.
569 
570   /// Block iterator.
571   /// @internal The reason for this is to override the increment operator.
572   class const_iterator : public std::forward_iterator_tag
573   {
574     using self_type = const_iterator; ///< Self reference type.
575   protected:
576     /// Current buffer block.
577     IOBufferBlock *_b = nullptr;
578 
579   public:
580     using value_type = const IOBufferBlock; ///< Iterator value type.
581 
582     const_iterator() = default; ///< Default constructor.
583 
584     /// Copy constructor.
585     // cppcheck-suppress noExplicitConstructor; copy constructor
586     const_iterator(self_type const &that);
587 
588     /// Assignment.
589     self_type &operator=(self_type const &that);
590 
591     /// Equality.
592     bool operator==(self_type const &that) const;
593     /// Inequality.
594     bool operator!=(self_type const &that) const;
595 
596     value_type &operator*() const;
597     value_type *operator->() const;
598 
599     self_type &operator++();
600     self_type operator++(int);
601   };
602 
603   class iterator : public const_iterator
604   {
605     using self_type = iterator; ///< Self reference type.
606   public:
607     using value_type = IOBufferBlock; ///< Dereferenced type.
608 
609     value_type &operator*() const;
610     value_type *operator->() const;
611   };
612 
613   using value_type = IOBufferBlock;
614 
615   iterator begin();
616   const_iterator begin() const;
617 
618   iterator end();
619   const_iterator end() const;
620 
621 protected:
622   /// Append @a block.
623   void append(IOBufferBlock *block);
624 
625   /// Head of buffer block chain.
626   Ptr<IOBufferBlock> _head;
627   /// Tail of the block chain.
628   IOBufferBlock *_tail = nullptr;
629   /// The amount of data of interest.
630   /// Not necessarily the amount of data in the chain of blocks.
631   int64_t _len = 0;
632 };
633 
634 /**
635   An independent reader from an MIOBuffer. A reader for a set of
636   IOBufferBlocks. The IOBufferReader represents the place where a given
637   consumer of buffer data is reading from. It provides a uniform interface
638   for easily accessing the data contained in a list of IOBufferBlocks
639   associated with the IOBufferReader.
640 
641   IOBufferReaders are the abstraction that determine when data blocks
642   can be removed from the buffer.
643 
644 */
645 class IOBufferReader
646 {
647 public:
648   /**
649     Start of unconsumed data. Returns a pointer to first unconsumed data
650     on the buffer for this reader. A null pointer indicates no data is
651     available. It uses the current start_offset value.
652 
653     @return pointer to the start of the unconsumed data.
654 
655   */
656   char *start();
657 
658   /**
659     End of inuse area of the first block with unconsumed data. Returns a
660     pointer to the end of the first block with unconsumed data for this
661     reader. A nullptr pointer indicates there are no blocks with unconsumed
662     data for this reader.
663 
664     @return pointer to the end of the first block with unconsumed data.
665 
666   */
667   char *end();
668 
669   /**
670     Amount of data available across all of the IOBufferBlocks. Returns the
671     number of unconsumed bytes of data available to this reader across
672     all remaining IOBufferBlocks. It subtracts the current start_offset
673     value from the total.
674 
675     @return bytes of data available across all the buffers.
676 
677   */
678   int64_t read_avail();
679 
680   /** Check if there is more than @a size bytes available to read.
681       @return @c true if more than @a size byte are available.
682   */
683   bool is_read_avail_more_than(int64_t size);
684 
685   /**
686     Number of IOBufferBlocks with data in the block list. Returns the
687     number of IOBufferBlocks on the block list with data remaining for
688     this reader.
689 
690     @return number of blocks with data for this reader.
691 
692   */
693   int block_count();
694 
695   /**
696     Amount of data available in the first buffer with data for this
697     reader.  Returns the number of unconsumed bytes of data available
698     on the first IOBufferBlock with data for this reader.
699 
700     @return number of unconsumed bytes of data available in the first
701       buffer.
702 
703   */
704   int64_t block_read_avail();
705 
706   /** Get a view of the data available to read.
707    *
708    * @return A view encompassing currently available readable data.
709    */
710   std::string_view block_read_view();
711 
712   void skip_empty_blocks();
713 
714   /**
715     Clears all fields in this IOBuffeReader, rendering it unusable. Drops
716     the reference to the IOBufferBlock list, the accessor, MIOBuffer and
717     resets this reader's state. You have to set those fields in order
718     to use this object again.
719 
720   */
721   void clear();
722 
723   /**
724     Instruct the reader to reset the IOBufferBlock list. Resets the
725     reader to the point to the start of the block where new data will
726     be written. After this call, the start_offset field is set to zero
727     and the list of IOBufferBlocks is set using the associated MIOBuffer.
728 
729   */
730   void reset();
731 
732   /**
733     Consume a number of bytes from this reader's IOBufferBlock
734     list. Advances the current position in the IOBufferBlock list of
735     this reader by n bytes.
736 
737     @param n number of bytes to consume. It must be less than or equal
738       to read_avail().
739 
740   */
741   void consume(int64_t n);
742 
743   /**
744     Create another reader with access to the same data as this
745     IOBufferReader. Allocates a new reader with the same state as this
746     IOBufferReader. This means that the new reader will point to the same
747     list of IOBufferBlocks and to the same buffer position as this reader.
748 
749     @return new reader with the same state as this.
750 
751   */
752   IOBufferReader *clone();
753 
754   /**
755     Deallocate this reader. Removes and deallocates this reader from
756     the underlying MIOBuffer. This IOBufferReader object must not be
757     used after this call.
758 
759   */
760   void dealloc();
761 
762   /**
763     Get a pointer to the first block with data. Returns a pointer to
764     the first IOBufferBlock in the block chain with data available for
765     this reader
766 
767     @return pointer to the first IOBufferBlock in the list with data
768       available for this reader.
769 
770   */
771   IOBufferBlock *get_current_block();
772 
773   /**
774     Consult this reader's MIOBuffer writable space. Queries the MIOBuffer
775     associated with this reader about the amount of writable space
776     available without adding any blocks on the buffer and returns true
777     if it is less than the water mark.
778 
779     @return true if the MIOBuffer associated with this IOBufferReader
780       returns true in MIOBuffer::current_low_water().
781 
782   */
783   bool current_low_water();
784 
785   /**
786     Queries the underlying MIOBuffer about. Returns true if the amount
787     of writable space after adding a block on the underlying MIOBuffer
788     is less than its water mark. This function call may add blocks to
789     the MIOBuffer (see MIOBuffer::low_water()).
790 
791     @return result of MIOBuffer::low_water() on the MIOBuffer for
792       this reader.
793 
794   */
795   bool low_water();
796 
797   /**
798     To see if the amount of data available to the reader is greater than
799     the MIOBuffer's water mark. Indicates whether the amount of data
800     available to this reader exceeds the water mark for this reader's
801     MIOBuffer.
802 
803     @return true if the amount of data exceeds the MIOBuffer's water mark.
804 
805   */
806   bool high_water();
807 
808   /**
809     Perform a memchr() across the list of IOBufferBlocks. Returns the
810     offset from the current start point of the reader to the first
811     occurrence of character 'c' in the buffer.
812 
813     @param c character to look for.
814     @param len number of characters to check. If len exceeds the number
815       of bytes available on the buffer or INT64_MAX is passed in, the
816       number of bytes available to the reader is used. It is independent
817       of the offset value.
818     @param offset number of the bytes to skip over before beginning
819       the operation.
820     @return -1 if c is not found, otherwise position of the first
821       occurrence.
822 
823   */
824   inkcoreapi int64_t memchr(char c, int64_t len = INT64_MAX, int64_t offset = 0);
825 
826   /**
827     Copies and consumes data. Copies len bytes of data from the buffer
828     into the supplied buffer, which must be allocated prior to the call
829     and it must be at large enough for the requested bytes. Once the
830     data is copied, it consumed from the reader.
831 
832     @param buf in which to place the data.
833     @param len bytes to copy and consume. If 'len' exceeds the bytes
834       available to the reader, the number of bytes available is used
835       instead.
836 
837     @return number of bytes copied and consumed.
838 
839   */
840   inkcoreapi int64_t read(void *buf, int64_t len);
841 
842   /**
843     Copy data but do not consume it. Copies 'len' bytes of data from
844     the current buffer into the supplied buffer. The copy skips the
845     number of bytes specified by 'offset' beyond the current point of
846     the reader. It also takes into account the current start_offset value.
847 
848     @param buf in which to place the data. The pointer is modified after
849       the call and points one position after the end of the data copied.
850     @param len bytes to copy. If len exceeds the bytes available to the
851       reader or INT64_MAX is passed in, the number of bytes available is
852       used instead. No data is consumed from the reader in this operation.
853     @param offset bytes to skip from the current position. The parameter
854       is modified after the call.
855     @return pointer to one position after the end of the data copied. The
856       parameter buf is set to this value also.
857 
858   */
859   inkcoreapi char *memcpy(void *buf, int64_t len = INT64_MAX, int64_t offset = 0);
860 
861   /**
862     Subscript operator. Returns a reference to the character at the
863     specified position. You must ensure that it is within an appropriate
864     range.
865 
866     @param i positions beyond the current point of the reader. It must
867       be less than the number of the bytes available to the reader.
868 
869     @return reference to the character in that position.
870 
871   */
872   char &operator[](int64_t i);
873 
874   MIOBuffer *
875   writer() const
876   {
877     return mbuf;
878   }
879   MIOBuffer *
880   allocated() const
881   {
882     return mbuf;
883   }
884 
885   MIOBufferAccessor *accessor = nullptr; // pointer back to the accessor
886 
887   /**
888     Back pointer to this object's MIOBuffer. A pointer back to the
889     MIOBuffer this reader is allocated from.
890 
891   */
892   MIOBuffer *mbuf = nullptr;
893   Ptr<IOBufferBlock> block;
894 
895   /**
896     Offset beyond the shared start(). The start_offset is used in the
897     calls that copy or consume data and is an offset at the beginning
898     of the available data.
899 
900   */
901   int64_t start_offset = 0;
902   int64_t size_limit   = INT64_MAX;
903 
904   IOBufferReader() {}
905 };
906 
907 /**
908   A multiple reader, single writer memory buffer. MIOBuffers are at
909   the center of all IOCore data transfer. MIOBuffers are the data
910   buffers used to transfer data to and from VConnections. A MIOBuffer
911   points to a list of IOBufferBlocks which in turn point to IOBufferData
912   structures that in turn point to the actual data. MIOBuffer allows one
913   producer and multiple consumers. The buffer fills up according the
914   amount of data outstanding for the slowest consumer. Thus, MIOBuffer
915   implements automatic flow control between readers of different speeds.
916   Data on IOBuffer is immutable. Once written it cannot be modified, only
917   deallocated once all consumers have finished with it. Immutability is
918   necessary since data can be shared between buffers, which means that
919   multiple IOBufferBlock objects may reference the same data but only
920   one will have ownership for writing.
921 
922 */
923 class MIOBuffer
924 {
925 public:
926   /**
927     Increase writer's inuse area. Instructs the writer associated with
928     this MIOBuffer to increase the inuse area of the block by as much as
929     'len' bytes.
930 
931     @param len number of bytes to add to the inuse area of the block.
932 
933   */
934   void fill(int64_t len);
935 
936   /**
937     Adds a block to the end of the block list. The block added to list
938     must be writable by this buffer and must not be writable by any
939     other buffer.
940 
941   */
942   void append_block(IOBufferBlock *b);
943 
944   /**
945     Adds a new block to the end of the block list. The size is determined
946     by asize_index. See the remarks section for a mapping of indexes to
947     buffer block sizes.
948 
949   */
950   void append_block(int64_t asize_index);
951 
952   /**
953     Adds new block to the end of block list using the block size for
954     the buffer specified when the buffer was allocated.
955 
956   */
957   void add_block();
958 
959   /**
960     Adds by reference len bytes of data pointed to by b to the end
961     of the buffer.  b MUST be a pointer to the beginning of  block
962     allocated from the ats_xmalloc() routine. The data will be deallocated
963     by the buffer once all readers on the buffer have consumed it.
964 
965   */
966   void append_xmalloced(void *b, int64_t len);
967 
968   /**
969     Adds by reference len bytes of data pointed to by b to the end of the
970     buffer. b MUST be a pointer to the beginning of  block allocated from
971     ioBufAllocator of the corresponding index for fast_size_index. The
972     data will be deallocated by the buffer once all readers on the buffer
973     have consumed it.
974 
975   */
976   void append_fast_allocated(void *b, int64_t len, int64_t fast_size_index);
977 
978   /**
979     Adds the nbytes worth of data pointed by rbuf to the buffer. The
980     data is copied into the buffer. write() does not respect watermarks
981     or buffer size limits. Users of write must implement their own flow
982     control. Returns the number of bytes added.
983 
984   */
985   inkcoreapi int64_t write(const void *rbuf, int64_t nbytes);
986 
987   /**
988     Add by data from IOBufferReader r to the this buffer by reference. If
989     len is INT64_MAX, all available data on the reader is added. If len is
990     less than INT64_MAX, the smaller of len or the amount of data on the
991     buffer is added. If offset is greater than zero, than the offset
992     bytes of data at the front of the reader are skipped. Bytes skipped
993     by offset reduce the number of bytes available on the reader used
994     in the amount of data to add computation. write() does not respect
995     watermarks or buffer size limits. Users of write must implement
996     their own flow control. Returns the number of bytes added. Each
997     write() call creates a new IOBufferBlock, even if it is for one
998     byte. As such, it's necessary to exercise caution in any code that
999     repeatedly transfers data from one buffer to another, especially if
1000     the data is being read over the network as it may be coming in very
1001     small chunks. Because deallocation of outstanding buffer blocks is
1002     recursive, it's possible to overrun the stack if too many blocks
1003     have been added to the buffer chain. It's imperative that users
1004     both implement their own flow control to prevent too many bytes
1005     from becoming outstanding on a buffer that the write() call is
1006     being used and that care be taken to ensure the transfers are of a
1007     minimum size. Should it be necessary to make a large number of small
1008     transfers, it's preferable to use a interface that copies the data
1009     rather than sharing blocks to prevent a build of blocks on the buffer.
1010 
1011   */
1012   inkcoreapi int64_t write(IOBufferReader *r, int64_t len = INT64_MAX, int64_t offset = 0);
1013 
1014   /** Copy data from the @a chain to this buffer.
1015       New IOBufferBlocks are allocated so this gets a copy of the data that is independent of the source.
1016       @a offset bytes are skipped at the start of the @a chain. The length is bounded by @a len and the
1017       size in the @a chain.
1018 
1019       @return the number of bytes copied.
1020 
1021       @internal I do not like counting @a offset against @a bytes but that's how @c write works...
1022   */
1023   int64_t write(IOBufferChain const *chain, int64_t len = INT64_MAX, int64_t offset = 0);
1024 
1025   int64_t remove_append(IOBufferReader *);
1026 
1027   /**
1028     Returns a pointer to the first writable block on the block chain.
1029     Returns nullptr if there are not currently any writable blocks on the
1030     block list.
1031   */
1032   IOBufferBlock *
1033   first_write_block()
1034   {
1035     if (_writer) {
1036       if (_writer->next && !_writer->write_avail()) {
1037         return _writer->next.get();
1038       }
1039       ink_assert(!_writer->next || !_writer->next->read_avail());
1040       return _writer.get();
1041     }
1042 
1043     return nullptr;
1044   }
1045 
1046   char *
1047   buf()
1048   {
1049     IOBufferBlock *b = first_write_block();
1050     return b ? b->buf() : nullptr;
1051   }
1052 
1053   char *
1054   buf_end()
1055   {
1056     return first_write_block()->buf_end();
1057   }
1058 
1059   char *
1060   start()
1061   {
1062     return first_write_block()->start();
1063   }
1064 
1065   char *
1066   end()
1067   {
1068     return first_write_block()->end();
1069   }
1070 
1071   /**
1072     Returns the amount of space of available for writing on the first
1073     writable block on the block chain (the one that would be returned
1074     by first_write_block()).
1075 
1076   */
1077   int64_t block_write_avail();
1078 
1079   /**
1080     Returns the amount of space of available for writing on all writable
1081     blocks currently on the block chain.  Will NOT add blocks to the
1082     block chain.
1083 
1084   */
1085   int64_t current_write_avail();
1086 
1087   /**
1088     Adds blocks for writing if the watermark criteria are met. Returns
1089     the amount of space of available for writing on all writable blocks
1090     on the block chain after a block due to the watermark criteria.
1091 
1092   */
1093   int64_t write_avail();
1094 
1095   /**
1096     Returns the default data block size for this buffer.
1097 
1098   */
1099   int64_t block_size();
1100 
1101   /**
1102     Returns the default data block size for this buffer.
1103 
1104   */
1105   int64_t
1106   total_size()
1107   {
1108     return block_size();
1109   }
1110 
1111   /**
1112     Returns true if amount of the data outstanding on the buffer exceeds
1113     the watermark.
1114 
1115   */
1116   bool
1117   high_water()
1118   {
1119     return max_read_avail() > water_mark;
1120   }
1121 
1122   /**
1123     Returns true if the amount of writable space after adding a block on
1124     the buffer is less than the water mark. Since this function relies
1125     on write_avail() it may add blocks.
1126 
1127   */
1128   bool
1129   low_water()
1130   {
1131     return write_avail() <= water_mark;
1132   }
1133 
1134   /**
1135     Returns true if amount the amount writable space without adding and
1136     blocks on the buffer is less than the water mark.
1137 
1138   */
1139   bool
1140   current_low_water()
1141   {
1142     return current_write_avail() <= water_mark;
1143   }
1144   void set_size_index(int64_t size);
1145 
1146   /**
1147     Allocates a new IOBuffer reader and sets it's its 'accessor' field
1148     to point to 'anAccessor'.
1149 
1150   */
1151   IOBufferReader *alloc_accessor(MIOBufferAccessor *anAccessor);
1152 
1153   /**
1154     Allocates an IOBufferReader for this buffer. IOBufferReaders hold
1155     data on the buffer for different consumers. IOBufferReaders are
1156     REQUIRED when using buffer. alloc_reader() MUST ONLY be a called
1157     on newly allocated buffers. Calling on a buffer with data already
1158     placed on it will result in the reader starting at an indeterminate
1159     place on the buffer.
1160 
1161   */
1162   IOBufferReader *alloc_reader();
1163 
1164   /**
1165     Allocates a new reader on this buffer and places it's starting
1166     point at the same place as reader r. r MUST be a pointer to a reader
1167     previous allocated from this buffer.
1168 
1169   */
1170   IOBufferReader *clone_reader(IOBufferReader *r);
1171 
1172   /**
1173     Deallocates reader e from this buffer. e MUST be a pointer to a reader
1174     previous allocated from this buffer. Reader need to allocated when a
1175     particularly consumer is being removed from the buffer but the buffer
1176     is still in use. Deallocation is not necessary when the buffer is
1177     being freed as all outstanding readers are automatically deallocated.
1178 
1179   */
1180   void dealloc_reader(IOBufferReader *e);
1181 
1182   /**
1183     Deallocates all outstanding readers on the buffer.
1184 
1185   */
1186   void dealloc_all_readers();
1187 
1188   void set(void *b, int64_t len);
1189   void set_xmalloced(void *b, int64_t len);
1190   void alloc(int64_t i = default_large_iobuffer_size);
1191   void alloc_xmalloc(int64_t buf_size);
1192   void append_block_internal(IOBufferBlock *b);
1193   int64_t write(IOBufferBlock const *b, int64_t len, int64_t offset);
1194   int64_t puts(char *buf, int64_t len);
1195 
1196   // internal interface
1197 
1198   bool
1199   empty()
1200   {
1201     return !_writer;
1202   }
1203   int64_t max_read_avail();
1204 
1205   int max_block_count();
1206   void check_add_block();
1207 
1208   IOBufferBlock *get_current_block();
1209 
1210   void
1211   reset()
1212   {
1213     if (_writer) {
1214       _writer->reset();
1215     }
1216     for (auto &reader : readers) {
1217       if (reader.allocated()) {
1218         reader.reset();
1219       }
1220     }
1221   }
1222 
1223   void
1224   init_readers()
1225   {
1226     for (auto &reader : readers) {
1227       if (reader.allocated() && !reader.block) {
1228         reader.block = _writer;
1229       }
1230     }
1231   }
1232 
1233   void
1234   dealloc()
1235   {
1236     _writer = nullptr;
1237     dealloc_all_readers();
1238   }
1239 
1240   void
1241   clear()
1242   {
1243     dealloc();
1244     size_index = BUFFER_SIZE_NOT_ALLOCATED;
1245     water_mark = 0;
1246   }
1247 
1248   void
1249   realloc(int64_t i)
1250   {
1251     _writer->realloc(i);
1252   }
1253   void
1254   realloc(void *b, int64_t buf_size)
1255   {
1256     _writer->realloc(b, buf_size);
1257   }
1258   void
1259   realloc_xmalloc(void *b, int64_t buf_size)
1260   {
1261     _writer->realloc_xmalloc(b, buf_size);
1262   }
1263   void
1264   realloc_xmalloc(int64_t buf_size)
1265   {
1266     _writer->realloc_xmalloc(buf_size);
1267   }
1268 
1269   int64_t size_index;
1270 
1271   /**
1272     Determines when to stop writing or reading. The watermark is the
1273     level to which the producer (filler) is required to fill the buffer
1274     before it can expect the reader to consume any data.  A watermark
1275     of zero means that the reader will consume any amount of data,
1276     no matter how small.
1277 
1278   */
1279   int64_t water_mark;
1280 
1281   Ptr<IOBufferBlock> _writer;
1282   IOBufferReader readers[MAX_MIOBUFFER_READERS];
1283 
1284 #ifdef TRACK_BUFFER_USER
1285   const char *_location = nullptr;
1286 #endif
1287 
1288   MIOBuffer(void *b, int64_t bufsize, int64_t aWater_mark);
1289   // cppcheck-suppress noExplicitConstructor; allow implicit conversion
1290   MIOBuffer(int64_t default_size_index);
1291   MIOBuffer();
1292   ~MIOBuffer();
1293 };
1294 
1295 /**
1296   A wrapper for either a reader or a writer of an MIOBuffer.
1297 
1298 */
1299 struct MIOBufferAccessor {
1300   IOBufferReader *
1301   reader()
1302   {
1303     return entry;
1304   }
1305 
1306   MIOBuffer *
1307   writer()
1308   {
1309     return mbuf;
1310   }
1311 
1312   int64_t
1313   block_size() const
1314   {
1315     return mbuf->block_size();
1316   }
1317 
1318   int64_t
1319   total_size() const
1320   {
1321     return block_size();
1322   }
1323 
1324   void reader_for(IOBufferReader *abuf);
1325   void reader_for(MIOBuffer *abuf);
1326   void writer_for(MIOBuffer *abuf);
1327 
1328   void
1329   clear()
1330   {
1331     mbuf  = nullptr;
1332     entry = nullptr;
1333   }
1334 
1335   MIOBufferAccessor() {}
1336 
1337   ~MIOBufferAccessor();
1338 
1339 #ifdef DEBUG
1340   const char *name = nullptr;
1341 #endif
1342 
1343   // noncopyable
1344   MIOBufferAccessor(const MIOBufferAccessor &) = delete;
1345   MIOBufferAccessor &operator=(const MIOBufferAccessor &) = delete;
1346 
1347 private:
1348   MIOBuffer *mbuf       = nullptr;
1349   IOBufferReader *entry = nullptr;
1350 };
1351 
1352 extern MIOBuffer *new_MIOBuffer_internal(
1353 #ifdef TRACK_BUFFER_USER
1354   const char *loc,
1355 #endif
1356   int64_t size_index = default_large_iobuffer_size);
1357 
1358 #ifdef TRACK_BUFFER_USER
1359 class MIOBuffer_tracker
1360 {
1361   const char *loc;
1362 
1363 public:
1364   explicit MIOBuffer_tracker(const char *_loc) : loc(_loc) {}
1365   MIOBuffer *
1366   operator()(int64_t size_index = default_large_iobuffer_size)
1367   {
1368     return new_MIOBuffer_internal(loc, size_index);
1369   }
1370 };
1371 #endif
1372 
1373 extern MIOBuffer *new_empty_MIOBuffer_internal(
1374 #ifdef TRACK_BUFFER_USER
1375   const char *loc,
1376 #endif
1377   int64_t size_index = default_large_iobuffer_size);
1378 
1379 #ifdef TRACK_BUFFER_USER
1380 class Empty_MIOBuffer_tracker
1381 {
1382   const char *loc;
1383 
1384 public:
1385   explicit Empty_MIOBuffer_tracker(const char *_loc) : loc(_loc) {}
1386   MIOBuffer *
1387   operator()(int64_t size_index = default_large_iobuffer_size)
1388   {
1389     return new_empty_MIOBuffer_internal(loc, size_index);
1390   }
1391 };
1392 #endif
1393 
1394 /// MIOBuffer allocator/deallocator
1395 #ifdef TRACK_BUFFER_USER
1396 #define new_MIOBuffer MIOBuffer_tracker(RES_PATH("memory/IOBuffer/"))
1397 #define new_empty_MIOBuffer Empty_MIOBuffer_tracker(RES_PATH("memory/IOBuffer/"))
1398 #else
1399 #define new_MIOBuffer new_MIOBuffer_internal
1400 #define new_empty_MIOBuffer new_empty_MIOBuffer_internal
1401 #endif
1402 extern void free_MIOBuffer(MIOBuffer *mio);
1403 //////////////////////////////////////////////////////////////////////
1404 
1405 extern IOBufferBlock *new_IOBufferBlock_internal(
1406 #ifdef TRACK_BUFFER_USER
1407   const char *loc
1408 #endif
1409 );
1410 
1411 extern IOBufferBlock *new_IOBufferBlock_internal(
1412 #ifdef TRACK_BUFFER_USER
1413   const char *loc,
1414 #endif
1415   IOBufferData *d, int64_t len = 0, int64_t offset = 0);
1416 
1417 #ifdef TRACK_BUFFER_USER
1418 class IOBufferBlock_tracker
1419 {
1420   const char *loc;
1421 
1422 public:
1423   explicit IOBufferBlock_tracker(const char *_loc) : loc(_loc) {}
1424   IOBufferBlock *
1425   operator()()
1426   {
1427     return new_IOBufferBlock_internal(loc);
1428   }
1429   IOBufferBlock *
1430   operator()(Ptr<IOBufferData> &d, int64_t len = 0, int64_t offset = 0)
1431   {
1432     return new_IOBufferBlock_internal(loc, d.get(), len, offset);
1433   }
1434 };
1435 #endif
1436 
1437 /// IOBufferBlock allocator
1438 #ifdef TRACK_BUFFER_USER
1439 #define new_IOBufferBlock IOBufferBlock_tracker(RES_PATH("memory/IOBuffer/"))
1440 #else
1441 #define new_IOBufferBlock new_IOBufferBlock_internal
1442 #endif
1443 ////////////////////////////////////////////////////////////
1444 
1445 extern IOBufferData *new_IOBufferData_internal(
1446 #ifdef TRACK_BUFFER_USER
1447   const char *location,
1448 #endif
1449   int64_t size_index = default_large_iobuffer_size, AllocType type = DEFAULT_ALLOC);
1450 
1451 extern IOBufferData *new_xmalloc_IOBufferData_internal(
1452 #ifdef TRACK_BUFFER_USER
1453   const char *location,
1454 #endif
1455   void *b, int64_t size);
1456 
1457 extern IOBufferData *new_constant_IOBufferData_internal(
1458 #ifdef TRACK_BUFFER_USER
1459   const char *locaction,
1460 #endif
1461   void *b, int64_t size);
1462 
1463 #ifdef TRACK_BUFFER_USER
1464 class IOBufferData_tracker
1465 {
1466   const char *loc;
1467 
1468 public:
1469   explicit IOBufferData_tracker(const char *_loc) : loc(_loc) {}
1470   IOBufferData *
1471   operator()(int64_t size_index = default_large_iobuffer_size, AllocType type = DEFAULT_ALLOC)
1472   {
1473     return new_IOBufferData_internal(loc, size_index, type);
1474   }
1475 };
1476 #endif
1477 
1478 #ifdef TRACK_BUFFER_USER
1479 #define new_IOBufferData IOBufferData_tracker(RES_PATH("memory/IOBuffer/"))
1480 #define new_xmalloc_IOBufferData(b, size) new_xmalloc_IOBufferData_internal(RES_PATH("memory/IOBuffer/"), (b), (size))
1481 #define new_constant_IOBufferData(b, size) new_constant_IOBufferData_internal(RES_PATH("memory/IOBuffer/"), (b), (size))
1482 #else
1483 #define new_IOBufferData new_IOBufferData_internal
1484 #define new_xmalloc_IOBufferData new_xmalloc_IOBufferData_internal
1485 #define new_constant_IOBufferData new_constant_IOBufferData_internal
1486 #endif
1487 
1488 extern int64_t iobuffer_size_to_index(int64_t size, int64_t max = max_iobuffer_size);
1489 extern int64_t index_to_buffer_size(int64_t idx);
1490 /**
1491   Clone a IOBufferBlock chain. Used to snarf a IOBufferBlock chain
1492   w/o copy.
1493 
1494   @param b head of source IOBufferBlock chain.
1495   @param offset # bytes in the beginning to skip.
1496   @param len bytes to copy from source.
1497   @return ptr to head of new IOBufferBlock chain.
1498 
1499 */
1500 extern IOBufferBlock *iobufferblock_clone(IOBufferBlock *b, int64_t offset, int64_t len);
1501 /**
1502   Skip over specified bytes in chain. Used for dropping references.
1503 
1504   @param b head of source IOBufferBlock chain.
1505   @param poffset originally offset in b, finally offset in returned
1506     IOBufferBlock.
1507   @param plen value of write is subtracted from plen in the function.
1508   @param write bytes to skip.
1509   @return ptr to head of new IOBufferBlock chain.
1510 
1511 */
1512 extern IOBufferBlock *iobufferblock_skip(IOBufferBlock *b, int64_t *poffset, int64_t *plen, int64_t write);
1513 
1514 inline IOBufferChain &
1515 IOBufferChain::operator=(self_type const &that)
1516 {
1517   _head = that._head;
1518   _tail = that._tail;
1519   _len  = that._len;
1520   return *this;
1521 }
1522 
1523 inline IOBufferChain &
1524 IOBufferChain::operator+=(self_type const &that)
1525 {
1526   if (nullptr == _head)
1527     *this = that;
1528   else {
1529     _tail->next = that._head;
1530     _tail       = that._tail;
1531     _len += that._len;
1532   }
1533   return *this;
1534 }
1535 
1536 inline int64_t
1537 IOBufferChain::length() const
1538 {
1539   return _len;
1540 }
1541 
1542 inline IOBufferBlock const *
1543 IOBufferChain::head() const
1544 {
1545   return _head.get();
1546 }
1547 
1548 inline IOBufferBlock *
1549 IOBufferChain::head()
1550 {
1551   return _head.get();
1552 }
1553 
1554 inline void
1555 IOBufferChain::clear()
1556 {
1557   _head = nullptr;
1558   _tail = nullptr;
1559   _len  = 0;
1560 }
1561 
1562 inline IOBufferChain::const_iterator::const_iterator(self_type const &that) : _b(that._b) {}
1563 
1564 inline IOBufferChain::const_iterator &
1565 IOBufferChain::const_iterator::operator=(self_type const &that)
1566 {
1567   _b = that._b;
1568   return *this;
1569 }
1570 
1571 inline bool
1572 IOBufferChain::const_iterator::operator==(self_type const &that) const
1573 {
1574   return _b == that._b;
1575 }
1576 
1577 inline bool
1578 IOBufferChain::const_iterator::operator!=(self_type const &that) const
1579 {
1580   return _b != that._b;
1581 }
1582 
1583 inline IOBufferChain::const_iterator::value_type &IOBufferChain::const_iterator::operator*() const
1584 {
1585   return *_b;
1586 }
1587 
1588 inline IOBufferChain::const_iterator::value_type *IOBufferChain::const_iterator::operator->() const
1589 {
1590   return _b;
1591 }
1592 
1593 inline IOBufferChain::const_iterator &
1594 IOBufferChain::const_iterator::operator++()
1595 {
1596   _b = _b->next.get();
1597   return *this;
1598 }
1599 
1600 inline IOBufferChain::const_iterator
1601 IOBufferChain::const_iterator::operator++(int)
1602 {
1603   self_type pre{*this};
1604   ++*this;
1605   return pre;
1606 }
1607 
1608 inline IOBufferChain::iterator::value_type &IOBufferChain::iterator::operator*() const
1609 {
1610   return *_b;
1611 }
1612 
1613 inline IOBufferChain::iterator::value_type *IOBufferChain::iterator::operator->() const
1614 {
1615   return _b;
1616 }
1617