00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #if !defined (_P_IOBuffer_h)
00027 #define _P_IOBuffer_h
00028
00029 #include "libts.h"
00030 #include "ink_resource.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 TS_INLINE int64_t
00043 buffer_size_to_index(int64_t size, int64_t max = max_iobuffer_size)
00044 {
00045 int64_t r = max;
00046
00047 while (r && BUFFER_SIZE_FOR_INDEX(r - 1) >= size)
00048 r--;
00049 return r;
00050 }
00051
00052 TS_INLINE int64_t
00053 iobuffer_size_to_index(int64_t size, int64_t max)
00054 {
00055 if (size > BUFFER_SIZE_FOR_INDEX(max))
00056 return BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(size);
00057 return buffer_size_to_index(size, max);
00058 }
00059
00060 TS_INLINE int64_t
00061 index_to_buffer_size(int64_t idx)
00062 {
00063 if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(idx))
00064 return BUFFER_SIZE_FOR_INDEX(idx);
00065 else if (BUFFER_SIZE_INDEX_IS_XMALLOCED(idx))
00066 return BUFFER_SIZE_FOR_XMALLOC(idx);
00067
00068 else if (BUFFER_SIZE_INDEX_IS_CONSTANT(idx))
00069 return BUFFER_SIZE_FOR_CONSTANT(idx);
00070
00071 return 0;
00072 }
00073
00074 TS_INLINE IOBufferBlock *
00075 iobufferblock_clone(IOBufferBlock * b, int64_t offset, int64_t len)
00076 {
00077
00078 IOBufferBlock *start_buf = NULL;
00079 IOBufferBlock *current_buf = NULL;
00080
00081 while (b && len >= 0) {
00082 char *start = b->_start;
00083 char *end = b->_end;
00084 int64_t max_bytes = end - start;
00085 max_bytes -= offset;
00086 if (max_bytes <= 0) {
00087 offset = -max_bytes;
00088 b = b->next;
00089 continue;
00090 }
00091 int64_t bytes = len;
00092 if (bytes >= max_bytes)
00093 bytes = max_bytes;
00094 IOBufferBlock *new_buf = b->clone();
00095 new_buf->_start += offset;
00096 new_buf->_buf_end = new_buf->_end = new_buf->_start + bytes;
00097 if (!start_buf) {
00098 start_buf = new_buf;
00099 current_buf = start_buf;
00100 } else {
00101 current_buf->next = new_buf;
00102 current_buf = new_buf;
00103 }
00104 len -= bytes;
00105 b = b->next;
00106 offset = 0;
00107 }
00108 return start_buf;
00109 }
00110
00111 TS_INLINE IOBufferBlock *
00112 iobufferblock_skip(IOBufferBlock * b, int64_t *poffset, int64_t *plen, int64_t write)
00113 {
00114 int64_t offset = *poffset;
00115 int64_t len = write;
00116 while (b && len >= 0) {
00117 int64_t max_bytes = b->read_avail();
00118 max_bytes -= offset;
00119 if (max_bytes <= 0) {
00120 offset = -max_bytes;
00121 b = b->next;
00122 continue;
00123 }
00124 if (len >= max_bytes) {
00125 b = b->next;
00126 len -= max_bytes;
00127 offset = 0;
00128 } else {
00129 offset = offset + len;
00130 break;
00131 }
00132 }
00133 *poffset = offset;
00134 *plen -= write;
00135 return b;
00136 }
00137
00138 #ifdef TRACK_BUFFER_USER
00139 extern Resource *res_lookup(const char *path);
00140
00141 TS_INLINE void
00142 iobuffer_mem_inc(const char *_loc, int64_t _size_index)
00143 {
00144 if (!res_track_memory)
00145 return;
00146
00147 if (!BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_size_index))
00148 return;
00149
00150 if (!_loc)
00151 _loc = "memory/IOBuffer/UNKNOWN-LOCATION";
00152 Resource *res = res_lookup(_loc);
00153 ink_assert(strcmp(_loc, res->path) == 0);
00154 #ifdef DEBUG
00155 int64_t r = ink_atomic_increment(&res->value, index_to_buffer_size(_size_index));
00156 ink_assert(r >= 0);
00157 #else
00158 ink_atomic_increment(&res->value, index_to_buffer_size(_size_index));
00159 #endif
00160 }
00161
00162 TS_INLINE void
00163 iobuffer_mem_dec(const char *_loc, int64_t _size_index)
00164 {
00165 if (!res_track_memory)
00166 return;
00167
00168 if (!BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_size_index))
00169 return;
00170 if (!_loc)
00171 _loc = "memory/IOBuffer/UNKNOWN-LOCATION";
00172 Resource *res = res_lookup(_loc);
00173 ink_assert(strcmp(_loc, res->path) == 0);
00174 #ifdef DEBUG
00175 int64_t r = ink_atomic_increment(&res->value, -index_to_buffer_size(_size_index));
00176 ink_assert(r >= index_to_buffer_size(_size_index));
00177 #else
00178 ink_atomic_increment(&res->value, -index_to_buffer_size(_size_index));
00179 #endif
00180 }
00181 #endif
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 TS_INLINE int64_t
00195 IOBufferData::block_size()
00196 {
00197 return index_to_buffer_size(_size_index);
00198 }
00199
00200 TS_INLINE IOBufferData *
00201 new_IOBufferData_internal(
00202 #ifdef TRACK_BUFFER_USER
00203 const char *location,
00204 #endif
00205 void *b, int64_t size, int64_t asize_index)
00206 {
00207 (void) size;
00208 IOBufferData *d = THREAD_ALLOC(ioDataAllocator, this_thread());
00209 d->_size_index = asize_index;
00210 ink_assert(BUFFER_SIZE_INDEX_IS_CONSTANT(asize_index)
00211 || size <= d->block_size());
00212 #ifdef TRACK_BUFFER_USER
00213 d->_location = location;
00214 #endif
00215 d->_data = (char *) b;
00216 return d;
00217 }
00218
00219 TS_INLINE IOBufferData *
00220 new_constant_IOBufferData_internal(
00221 #ifdef TRACK_BUFFER_USER
00222 const char *loc,
00223 #endif
00224 void *b, int64_t size)
00225 {
00226 return new_IOBufferData_internal(
00227 #ifdef TRACK_BUFFER_USER
00228 loc,
00229 #endif
00230 b, size, BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(size));
00231 }
00232
00233 TS_INLINE IOBufferData *
00234 new_xmalloc_IOBufferData_internal(
00235 #ifdef TRACK_BUFFER_USER
00236 const char *location,
00237 #endif
00238 void *b, int64_t size)
00239 {
00240 return new_IOBufferData_internal(
00241 #ifdef TRACK_BUFFER_USER
00242 location,
00243 #endif
00244 b, size, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(size));
00245 }
00246
00247 TS_INLINE IOBufferData *
00248 new_IOBufferData_internal(
00249 #ifdef TRACK_BUFFER_USER
00250 const char *location,
00251 #endif
00252 void *b, int64_t size)
00253 {
00254 return new_IOBufferData_internal(
00255 #ifdef TRACK_BUFFER_USER
00256 location,
00257 #endif
00258 b, size, iobuffer_size_to_index(size));
00259 }
00260
00261 TS_INLINE IOBufferData *
00262 new_IOBufferData_internal(
00263 #ifdef TRACK_BUFFER_USER
00264 const char *loc,
00265 #endif
00266 int64_t size_index, AllocType type)
00267 {
00268 IOBufferData *d = THREAD_ALLOC(ioDataAllocator, this_thread());
00269 #ifdef TRACK_BUFFER_USER
00270 d->_location = loc;
00271 #endif
00272 d->alloc(size_index, type);
00273 return d;
00274 }
00275
00276
00277
00278
00279
00280 TS_INLINE void
00281 IOBufferData::alloc(int64_t size_index, AllocType type)
00282 {
00283 if (_data)
00284 dealloc();
00285 _size_index = size_index;
00286 _mem_type = type;
00287 #ifdef TRACK_BUFFER_USER
00288 iobuffer_mem_inc(_location, size_index);
00289 #endif
00290 switch (type) {
00291 case MEMALIGNED:
00292 if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(size_index))
00293 _data = (char *) ioBufAllocator[size_index].alloc_void();
00294
00295 else if (BUFFER_SIZE_INDEX_IS_XMALLOCED(size_index))
00296 _data = (char *)ats_memalign(ats_pagesize(), index_to_buffer_size(size_index));
00297 break;
00298 default:
00299 case DEFAULT_ALLOC:
00300 if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(size_index))
00301 _data = (char *) ioBufAllocator[size_index].alloc_void();
00302 else if (BUFFER_SIZE_INDEX_IS_XMALLOCED(size_index))
00303 _data = (char *)ats_malloc(BUFFER_SIZE_FOR_XMALLOC(size_index));
00304 break;
00305 }
00306 }
00307
00308
00309
00310
00311 TS_INLINE void
00312 IOBufferData::dealloc()
00313 {
00314 #ifdef TRACK_BUFFER_USER
00315 iobuffer_mem_dec(_location, _size_index);
00316 #endif
00317 switch (_mem_type) {
00318 case MEMALIGNED:
00319 if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_size_index))
00320 ioBufAllocator[_size_index].free_void(_data);
00321 else if (BUFFER_SIZE_INDEX_IS_XMALLOCED(_size_index))
00322 ::free((void *) _data);
00323 break;
00324 default:
00325 case DEFAULT_ALLOC:
00326 if (BUFFER_SIZE_INDEX_IS_FAST_ALLOCATED(_size_index))
00327 ioBufAllocator[_size_index].free_void(_data);
00328 else if (BUFFER_SIZE_INDEX_IS_XMALLOCED(_size_index))
00329 ats_free(_data);
00330 break;
00331 }
00332 _data = 0;
00333 _size_index = BUFFER_SIZE_NOT_ALLOCATED;
00334 _mem_type = NO_ALLOC;
00335 }
00336
00337 TS_INLINE void
00338 IOBufferData::free()
00339 {
00340 dealloc();
00341 THREAD_FREE(this, ioDataAllocator, this_thread());
00342 }
00343
00344
00345
00346
00347
00348
00349
00350 TS_INLINE IOBufferBlock *
00351 new_IOBufferBlock_internal(
00352 #ifdef TRACK_BUFFER_USER
00353 const char *location
00354 #endif
00355 )
00356 {
00357 IOBufferBlock *b = THREAD_ALLOC(ioBlockAllocator, this_thread());
00358 #ifdef TRACK_BUFFER_USER
00359 b->_location = location;
00360 #endif
00361 return b;
00362 }
00363
00364 TS_INLINE IOBufferBlock *
00365 new_IOBufferBlock_internal(
00366 #ifdef TRACK_BUFFER_USER
00367 const char *location,
00368 #endif
00369 IOBufferData * d, int64_t len, int64_t offset)
00370 {
00371 IOBufferBlock *b = THREAD_ALLOC(ioBlockAllocator, this_thread());
00372 #ifdef TRACK_BUFFER_USER
00373 b->_location = location;
00374 #endif
00375 b->set(d, len, offset);
00376 return b;
00377 }
00378
00379 TS_INLINE
00380 IOBufferBlock::IOBufferBlock():
00381 _start(0),
00382 _end(0),
00383 _buf_end(0)
00384 #ifdef TRACK_BUFFER_USER
00385 ,
00386 _location(0)
00387 #endif
00388 {
00389 return;
00390 }
00391
00392 TS_INLINE void
00393 IOBufferBlock::consume(int64_t len)
00394 {
00395 _start += len;
00396 ink_assert(_start <= _end);
00397 }
00398
00399 TS_INLINE void
00400 IOBufferBlock::fill(int64_t len)
00401 {
00402 _end += len;
00403 ink_assert(_end <= _buf_end);
00404 }
00405
00406 TS_INLINE void
00407 IOBufferBlock::reset()
00408 {
00409 _end = _start = buf();
00410 _buf_end = buf() + data->block_size();
00411 }
00412
00413 TS_INLINE void
00414 IOBufferBlock::alloc(int64_t i)
00415 {
00416 ink_assert(BUFFER_SIZE_ALLOCATED(i));
00417 #ifdef TRACK_BUFFER_USER
00418 data = new_IOBufferData_internal(_location, i);
00419 #else
00420 data = new_IOBufferData_internal(i);
00421 #endif
00422 reset();
00423 }
00424
00425 TS_INLINE void
00426 IOBufferBlock::clear()
00427 {
00428 data = NULL;
00429 IOBufferBlock *p = next;
00430 while (p) {
00431 int r = p->refcount_dec();
00432 if (r)
00433 break;
00434 else {
00435 IOBufferBlock *n = p->next.m_ptr;
00436 p->next.m_ptr = NULL;
00437 p->free();
00438 p = n;
00439 }
00440 }
00441 next.m_ptr = NULL;
00442 _buf_end = _end = _start = NULL;
00443 }
00444
00445 TS_INLINE IOBufferBlock *
00446 IOBufferBlock::clone()
00447 {
00448 #ifdef TRACK_BUFFER_USER
00449 IOBufferBlock *b = new_IOBufferBlock_internal(_location);
00450 #else
00451 IOBufferBlock *b = new_IOBufferBlock_internal();
00452 #endif
00453 b->data = data;
00454 b->_start = _start;
00455 b->_end = _end;
00456 b->_buf_end = _end;
00457 #ifdef TRACK_BUFFER_USER
00458 b->_location = _location;
00459 #endif
00460 return b;
00461 }
00462
00463 TS_INLINE void
00464 IOBufferBlock::dealloc()
00465 {
00466 clear();
00467 }
00468
00469 TS_INLINE void
00470 IOBufferBlock::free()
00471 {
00472 dealloc();
00473 THREAD_FREE(this, ioBlockAllocator, this_thread());
00474 }
00475
00476 TS_INLINE void
00477 IOBufferBlock::set_internal(void *b, int64_t len, int64_t asize_index)
00478 {
00479 #ifdef TRACK_BUFFER_USER
00480 data = new_IOBufferData_internal(_location, BUFFER_SIZE_NOT_ALLOCATED);
00481 #else
00482 data = new_IOBufferData_internal(BUFFER_SIZE_NOT_ALLOCATED);
00483 #endif
00484 data->_data = (char *) b;
00485 #ifdef TRACK_BUFFER_USER
00486 iobuffer_mem_inc(_location, asize_index);
00487 #endif
00488 data->_size_index = asize_index;
00489 reset();
00490 _end = _start + len;
00491 }
00492
00493 TS_INLINE void
00494 IOBufferBlock::set(IOBufferData * d, int64_t len, int64_t offset)
00495 {
00496 data = d;
00497 _start = buf() + offset;
00498 _end = _start + len;
00499 _buf_end = _start + d->block_size();
00500 }
00501
00502 TS_INLINE void
00503 IOBufferBlock::realloc_set_internal(void *b, int64_t buf_size, int64_t asize_index)
00504 {
00505 int64_t data_size = size();
00506 memcpy(b, _start, size());
00507 dealloc();
00508 set_internal(b, buf_size, asize_index);
00509 _end = _start + data_size;
00510 }
00511
00512 TS_INLINE void
00513 IOBufferBlock::realloc(void *b, int64_t buf_size)
00514 {
00515 realloc_set_internal(b, buf_size, BUFFER_SIZE_NOT_ALLOCATED);
00516 }
00517
00518 TS_INLINE void
00519 IOBufferBlock::realloc_xmalloc(void *b, int64_t buf_size)
00520 {
00521 realloc_set_internal(b, buf_size, -buf_size);
00522 }
00523
00524 TS_INLINE void
00525 IOBufferBlock::realloc_xmalloc(int64_t buf_size)
00526 {
00527 realloc_set_internal(ats_malloc(buf_size), buf_size, -buf_size);
00528 }
00529
00530 TS_INLINE void
00531 IOBufferBlock::realloc(int64_t i)
00532 {
00533 if ((i == data->_size_index) || (i >= (int64_t)countof(ioBufAllocator))) {
00534 return;
00535 }
00536
00537 ink_release_assert(i > data->_size_index && i != BUFFER_SIZE_NOT_ALLOCATED);
00538 void *b = ioBufAllocator[i].alloc_void();
00539 realloc_set_internal(b, BUFFER_SIZE_FOR_INDEX(i), i);
00540 }
00541
00542
00543
00544
00545
00546
00547
00548 TS_INLINE void
00549 IOBufferReader::skip_empty_blocks()
00550 {
00551 while (block->next && block->next->read_avail() && start_offset >= block->size()) {
00552 start_offset -= block->size();
00553 block = block->next;
00554 }
00555 }
00556
00557 TS_INLINE bool
00558 IOBufferReader::low_water()
00559 {
00560 return mbuf->low_water();
00561 }
00562
00563 TS_INLINE bool
00564 IOBufferReader::high_water()
00565 {
00566 return read_avail() >= mbuf->water_mark;
00567 }
00568
00569 TS_INLINE bool
00570 IOBufferReader::current_low_water()
00571 {
00572 return mbuf->current_low_water();
00573 }
00574
00575 TS_INLINE IOBufferBlock *
00576 IOBufferReader::get_current_block()
00577 {
00578 return block;
00579 }
00580
00581 TS_INLINE char *
00582 IOBufferReader::start()
00583 {
00584 if (block == 0)
00585 return 0;
00586 skip_empty_blocks();
00587 return block->start() + start_offset;
00588 }
00589
00590 TS_INLINE char *
00591 IOBufferReader::end()
00592 {
00593 if (block == 0)
00594 return 0;
00595 skip_empty_blocks();
00596 return block->end();
00597 }
00598
00599 TS_INLINE int64_t
00600 IOBufferReader::block_read_avail()
00601 {
00602 if (block == 0)
00603 return 0;
00604 skip_empty_blocks();
00605 return (int64_t) (block->end() - (block->start() + start_offset));
00606 }
00607
00608 TS_INLINE int
00609 IOBufferReader::block_count()
00610 {
00611 int count = 0;
00612 IOBufferBlock *b = block;
00613
00614 while (b) {
00615 count++;
00616 b = b->next;
00617 }
00618 return count;
00619 }
00620
00621 TS_INLINE int64_t
00622 IOBufferReader::read_avail()
00623 {
00624 int64_t t = 0;
00625 IOBufferBlock *b = block;
00626
00627 while (b) {
00628 t += b->read_avail();
00629 b = b->next;
00630 }
00631 t -= start_offset;
00632 if (size_limit != INT64_MAX && t > size_limit)
00633 t = size_limit;
00634 return t;
00635 }
00636
00637 inline bool
00638 IOBufferReader::is_read_avail_more_than(int64_t size)
00639 {
00640 int64_t t = -start_offset;
00641 IOBufferBlock* b = block;
00642 while (b) {
00643 t += b->read_avail();
00644 if (t > size) {
00645 return true;
00646 }
00647 b = b->next;
00648 }
00649 return false;
00650 }
00651
00652 TS_INLINE void
00653 IOBufferReader::consume(int64_t n)
00654 {
00655 start_offset += n;
00656 if (size_limit != INT64_MAX)
00657 size_limit -= n;
00658 ink_assert(size_limit >= 0);
00659 if (block == 0)
00660 return;
00661 int64_t r = block->read_avail();
00662 int64_t s = start_offset;
00663 while (r <= s && block->next && block->next->read_avail()) {
00664 s -= r;
00665 start_offset = s;
00666 block = block->next;
00667 r = block->read_avail();
00668 }
00669 ink_assert(read_avail() >= 0);
00670 }
00671
00672 TS_INLINE char &
00673 IOBufferReader::operator[] (int64_t i)
00674 {
00675 static char
00676 _error = '\0';
00677
00678 IOBufferBlock *
00679 b = block;
00680 i += start_offset;
00681 while (b) {
00682 int64_t bytes = b->read_avail();
00683 if (bytes > i)
00684 return b->start()[i];
00685 i -= bytes;
00686 b = b->next;
00687 }
00688
00689 ink_assert(!"out of range");
00690 if (unlikely(b))
00691 return *b->start();
00692
00693 return _error;
00694 }
00695
00696 TS_INLINE void
00697 IOBufferReader::clear()
00698 {
00699 accessor = NULL;
00700 block = NULL;
00701 mbuf = NULL;
00702 start_offset = 0;
00703 size_limit = INT64_MAX;
00704 }
00705
00706 TS_INLINE void
00707 IOBufferReader::reset()
00708 {
00709 block = mbuf->_writer;
00710 start_offset = 0;
00711 size_limit = INT64_MAX;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 inkcoreapi extern ClassAllocator<MIOBuffer> ioAllocator;
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734 TS_INLINE
00735 MIOBuffer::MIOBuffer(void *b, int64_t bufsize, int64_t aWater_mark)
00736 {
00737 #ifdef TRACK_BUFFER_USER
00738 _location = NULL;
00739 #endif
00740 set(b, bufsize);
00741 water_mark = aWater_mark;
00742 size_index = BUFFER_SIZE_NOT_ALLOCATED;
00743 return;
00744 }
00745
00746 TS_INLINE
00747 MIOBuffer::MIOBuffer(int64_t default_size_index)
00748 {
00749 clear();
00750 size_index = default_size_index;
00751 #ifdef TRACK_BUFFER_USER
00752 _location = NULL;
00753 #endif
00754 return;
00755 }
00756
00757 TS_INLINE
00758 MIOBuffer::MIOBuffer()
00759 {
00760 clear();
00761 #ifdef TRACK_BUFFER_USER
00762 _location = NULL;
00763 #endif
00764 return;
00765 }
00766
00767 TS_INLINE
00768 MIOBuffer::~
00769 MIOBuffer()
00770 {
00771 _writer = NULL;
00772 dealloc_all_readers();
00773 }
00774
00775 TS_INLINE MIOBuffer * new_MIOBuffer_internal(
00776 #ifdef TRACK_BUFFER_USER
00777 const char *location,
00778 #endif
00779 int64_t size_index)
00780 {
00781 MIOBuffer *b = THREAD_ALLOC(ioAllocator, this_thread());
00782 #ifdef TRACK_BUFFER_USER
00783 b->_location = location;
00784 #endif
00785 b->alloc(size_index);
00786 return b;
00787 }
00788
00789 TS_INLINE void
00790 free_MIOBuffer(MIOBuffer * mio)
00791 {
00792 mio->_writer = NULL;
00793 mio->dealloc_all_readers();
00794 THREAD_FREE(mio, ioAllocator, this_thread());
00795 }
00796
00797 TS_INLINE MIOBuffer * new_empty_MIOBuffer_internal(
00798 #ifdef TRACK_BUFFER_USER
00799 const char *location,
00800 #endif
00801 int64_t size_index)
00802 {
00803 MIOBuffer *b = THREAD_ALLOC(ioAllocator, this_thread());
00804 b->size_index = size_index;
00805 #ifdef TRACK_BUFFER_USER
00806 b->_location = location;
00807 #endif
00808 return b;
00809 }
00810
00811 TS_INLINE void
00812 free_empty_MIOBuffer(MIOBuffer * mio)
00813 {
00814 THREAD_FREE(mio, ioAllocator, this_thread());
00815 }
00816
00817 TS_INLINE IOBufferReader *
00818 MIOBuffer::alloc_accessor(MIOBufferAccessor * anAccessor)
00819 {
00820 int i;
00821 for (i = 0; i < MAX_MIOBUFFER_READERS; i++)
00822 if (!readers[i].allocated())
00823 break;
00824
00825
00826 ink_release_assert(i < MAX_MIOBUFFER_READERS);
00827
00828 IOBufferReader *e = &readers[i];
00829 e->mbuf = this;
00830 e->reset();
00831 e->accessor = anAccessor;
00832
00833 return e;
00834 }
00835
00836 TS_INLINE IOBufferReader *
00837 MIOBuffer::alloc_reader()
00838 {
00839 int i;
00840 for (i = 0; i < MAX_MIOBUFFER_READERS; i++)
00841 if (!readers[i].allocated())
00842 break;
00843
00844
00845 ink_release_assert(i < MAX_MIOBUFFER_READERS);
00846
00847 IOBufferReader *e = &readers[i];
00848 e->mbuf = this;
00849 e->reset();
00850 e->accessor = NULL;
00851
00852 return e;
00853 }
00854
00855 TS_INLINE int64_t
00856 MIOBuffer::block_size()
00857 {
00858 return index_to_buffer_size(size_index);
00859 }
00860 TS_INLINE IOBufferReader *
00861 MIOBuffer::clone_reader(IOBufferReader * r)
00862 {
00863 int i;
00864 for (i = 0; i < MAX_MIOBUFFER_READERS; i++)
00865 if (!readers[i].allocated())
00866 break;
00867
00868
00869 ink_release_assert(i < MAX_MIOBUFFER_READERS);
00870
00871 IOBufferReader *e = &readers[i];
00872 e->mbuf = this;
00873 e->accessor = NULL;
00874 e->block = r->block;
00875 e->start_offset = r->start_offset;
00876 e->size_limit = r->size_limit;
00877 ink_assert(e->size_limit >= 0);
00878
00879 return e;
00880 }
00881
00882 TS_INLINE int64_t
00883 MIOBuffer::block_write_avail()
00884 {
00885 IOBufferBlock *b = first_write_block();
00886 return b ? b->write_avail() : 0;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 TS_INLINE void
00905 MIOBuffer::append_block_internal(IOBufferBlock * b)
00906 {
00907
00908
00909
00910 if (!_writer) {
00911 _writer = b;
00912 init_readers();
00913 } else {
00914 ink_assert(!_writer->next || !_writer->next->read_avail());
00915 _writer->next = b;
00916 while (b->read_avail()) {
00917 _writer = b;
00918 b = b->next;
00919 if (!b)
00920 break;
00921 }
00922 }
00923 while (_writer->next && !_writer->write_avail() && _writer->next->read_avail())
00924 _writer = _writer->next;
00925 }
00926
00927 TS_INLINE void
00928 MIOBuffer::append_block(IOBufferBlock * b)
00929 {
00930 ink_assert(b->read_avail());
00931 append_block_internal(b);
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942 TS_INLINE void
00943 MIOBuffer::append_block(int64_t asize_index)
00944 {
00945 ink_assert(BUFFER_SIZE_ALLOCATED(asize_index));
00946 #ifdef TRACK_BUFFER_USER
00947 IOBufferBlock *b = new_IOBufferBlock_internal(_location);
00948 #else
00949 IOBufferBlock *b = new_IOBufferBlock_internal();
00950 #endif
00951 b->alloc(asize_index);
00952 append_block_internal(b);
00953 return;
00954 }
00955
00956 TS_INLINE void
00957 MIOBuffer::add_block()
00958 {
00959 append_block(size_index);
00960 }
00961
00962 TS_INLINE void
00963 MIOBuffer::check_add_block()
00964 {
00965 if (!high_water() && current_low_water())
00966 add_block();
00967 }
00968
00969 TS_INLINE IOBufferBlock *
00970 MIOBuffer::get_current_block()
00971 {
00972 return first_write_block();
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985 TS_INLINE int64_t
00986 MIOBuffer::current_write_avail()
00987 {
00988 int64_t t = 0;
00989 IOBufferBlock *b = _writer;
00990 while (b) {
00991 t += b->write_avail();
00992 b = b->next;
00993 }
00994 return t;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 TS_INLINE int64_t
01007 MIOBuffer::write_avail()
01008 {
01009 check_add_block();
01010 return current_write_avail();
01011 }
01012
01013 TS_INLINE void
01014 MIOBuffer::fill(int64_t len)
01015 {
01016 int64_t f = _writer->write_avail();
01017 while (f < len) {
01018 _writer->fill(f);
01019 len -= f;
01020 if (len > 0)
01021 _writer = _writer->next;
01022 f = _writer->write_avail();
01023 }
01024 _writer->fill(len);
01025 }
01026
01027 TS_INLINE int
01028 MIOBuffer::max_block_count()
01029 {
01030 int maxb = 0;
01031 for (int i = 0; i < MAX_MIOBUFFER_READERS; i++) {
01032 if (readers[i].allocated()) {
01033 int c = readers[i].block_count();
01034 if (c > maxb) {
01035 maxb = c;
01036 }
01037 }
01038 }
01039 return maxb;
01040 }
01041
01042 TS_INLINE int64_t
01043 MIOBuffer::max_read_avail()
01044 {
01045 int64_t s = 0;
01046 int found = 0;
01047 for (int i = 0; i < MAX_MIOBUFFER_READERS; i++) {
01048 if (readers[i].allocated()) {
01049 int64_t ss = readers[i].read_avail();
01050 if (ss > s) {
01051 s = ss;
01052 }
01053 found = 1;
01054 }
01055 }
01056 if (!found && _writer)
01057 return _writer->read_avail();
01058 return s;
01059 }
01060
01061 TS_INLINE void
01062 MIOBuffer::set(void *b, int64_t len)
01063 {
01064 #ifdef TRACK_BUFFER_USER
01065 _writer = new_IOBufferBlock_internal(_location);
01066 #else
01067 _writer = new_IOBufferBlock_internal();
01068 #endif
01069 _writer->set_internal(b, len, BUFFER_SIZE_INDEX_FOR_CONSTANT_SIZE(len));
01070 init_readers();
01071 }
01072
01073 TS_INLINE void
01074 MIOBuffer::set_xmalloced(void *b, int64_t len)
01075 {
01076 #ifdef TRACK_BUFFER_USER
01077 _writer = new_IOBufferBlock_internal(_location);
01078 #else
01079 _writer = new_IOBufferBlock_internal();
01080 #endif
01081 _writer->set_internal(b, len, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(len));
01082 init_readers();
01083 }
01084
01085 TS_INLINE void
01086 MIOBuffer::append_xmalloced(void *b, int64_t len)
01087 {
01088 #ifdef TRACK_BUFFER_USER
01089 IOBufferBlock *x = new_IOBufferBlock_internal(_location);
01090 #else
01091 IOBufferBlock *x = new_IOBufferBlock_internal();
01092 #endif
01093 x->set_internal(b, len, BUFFER_SIZE_INDEX_FOR_XMALLOC_SIZE(len));
01094 append_block_internal(x);
01095 }
01096
01097 TS_INLINE void
01098 MIOBuffer::append_fast_allocated(void *b, int64_t len, int64_t fast_size_index)
01099 {
01100 #ifdef TRACK_BUFFER_USER
01101 IOBufferBlock *x = new_IOBufferBlock_internal(_location);
01102 #else
01103 IOBufferBlock *x = new_IOBufferBlock_internal();
01104 #endif
01105 x->set_internal(b, len, fast_size_index);
01106 append_block_internal(x);
01107 }
01108
01109 TS_INLINE void
01110 MIOBuffer::alloc(int64_t i)
01111 {
01112 #ifdef TRACK_BUFFER_USER
01113 _writer = new_IOBufferBlock_internal(_location);
01114 #else
01115 _writer = new_IOBufferBlock_internal();
01116 #endif
01117 _writer->alloc(i);
01118 size_index = i;
01119 init_readers();
01120 }
01121
01122 TS_INLINE void
01123 MIOBuffer::alloc_xmalloc(int64_t buf_size)
01124 {
01125 char *b = (char *)ats_malloc(buf_size);
01126 set_xmalloced(b, buf_size);
01127 }
01128
01129 TS_INLINE void
01130 MIOBuffer::dealloc_reader(IOBufferReader * e)
01131 {
01132 if (e->accessor) {
01133 ink_assert(e->accessor->writer() == this);
01134 ink_assert(e->accessor->reader() == e);
01135 e->accessor->clear();
01136 }
01137 e->clear();
01138 }
01139
01140 TS_INLINE IOBufferReader *
01141 IOBufferReader::clone()
01142 {
01143 return mbuf->clone_reader(this);
01144 }
01145
01146 TS_INLINE void
01147 IOBufferReader::dealloc()
01148 {
01149 mbuf->dealloc_reader(this);
01150 }
01151
01152 TS_INLINE void
01153 MIOBuffer::dealloc_all_readers()
01154 {
01155 for (int i = 0; i < MAX_MIOBUFFER_READERS; i++)
01156 if (readers[i].allocated())
01157 dealloc_reader(&readers[i]);
01158 }
01159
01160 TS_INLINE void
01161 MIOBuffer::set_size_index(int64_t size)
01162 {
01163 size_index = iobuffer_size_to_index(size);
01164 }
01165
01166 TS_INLINE void
01167 MIOBufferAccessor::reader_for(MIOBuffer * abuf)
01168 {
01169 mbuf = abuf;
01170 if (abuf)
01171 entry = mbuf->alloc_accessor(this);
01172 else
01173 entry = NULL;
01174 }
01175
01176 TS_INLINE void
01177 MIOBufferAccessor::reader_for(IOBufferReader * areader)
01178 {
01179 if (entry == areader)
01180 return;
01181 mbuf = areader->mbuf;
01182 entry = areader;
01183 ink_assert(mbuf);
01184 }
01185
01186 TS_INLINE void
01187 MIOBufferAccessor::writer_for(MIOBuffer * abuf)
01188 {
01189 mbuf = abuf;
01190 entry = NULL;
01191 }
01192
01193 TS_INLINE
01194 MIOBufferAccessor::~
01195 MIOBufferAccessor()
01196 {
01197 }
01198
01199 #endif