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