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