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