• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

P_IOBuffer.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
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 // TODO: I think we're overly aggressive here on making MIOBuffer 64-bit
00034 // but not sure it's worthwhile changing anything to 32-bit honestly.
00035 
00036 //////////////////////////////////////////////////////////////
00037 //
00038 // returns 0 for DEFAULT_BUFFER_BASE_SIZE,
00039 // +1 for each power of 2
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   // coverity[dead_error_condition]
00068   else if (BUFFER_SIZE_INDEX_IS_CONSTANT(idx))
00069     return BUFFER_SIZE_FOR_CONSTANT(idx);
00070   // coverity[dead_error_line]
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 // inline functions definitions
00186 //
00187 //////////////////////////////////////////////////////////////////
00188 //////////////////////////////////////////////////////////////////
00189 //
00190 //  class IOBufferData --
00191 //         inline functions definitions
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 // IRIX has a compiler bug which prevents this function
00277 // from being compiled correctly at -O3
00278 // so it is DUPLICATED in IOBuffer.cc
00279 // ****** IF YOU CHANGE THIS FUNCTION change that one as well.
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     // coverity[dead_error_condition]
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 // ****** IF YOU CHANGE THIS FUNCTION change that one as well.
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 //  class IOBufferBlock --
00347 //         inline functions definitions
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 //  class IOBufferReader --
00545 //         inline functions definitions
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 //  class MIOBuffer --
00717 //      inline functions definitions
00718 //
00719 ////////////////////////////////////////////////////////////////
00720 inkcoreapi extern ClassAllocator<MIOBuffer> ioAllocator;
00721 ////////////////////////////////////////////////////////////////
00722 //
00723 //  MIOBuffer::MIOBuffer()
00724 //
00725 //  This constructor accepts a pre-allocated memory buffer,
00726 //  wraps if in a IOBufferData and IOBufferBlock structures
00727 //  and sets it as the current block.
00728 //  NOTE that in this case the memory buffer will not be freed
00729 //  by the MIOBuffer class. It is the user responsibility to
00730 //  free the memory buffer. The wrappers (MIOBufferBlock and
00731 //  MIOBufferData) will be freed by this class.
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   // TODO refactor code to return NULL at some point
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   // TODO refactor code to return NULL at some point
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   // TODO refactor code to return NULL at some point
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 //  MIOBuffer::append_block()
00892 //
00893 //  Appends a block to writer->next and make it the current
00894 //  block.
00895 //  Note that the block is not appended to the end of the list.
00896 //  That means that if writer->next was not null before this
00897 //  call then the block that writer->next was pointing to will
00898 //  have its reference count decremented and writer->next
00899 //  will have a new value which is the new block.
00900 //  In any case the new appended block becomes the current
00901 //  block.
00902 //
00903 ////////////////////////////////////////////////////////////////
00904 TS_INLINE void
00905 MIOBuffer::append_block_internal(IOBufferBlock * b)
00906 {
00907   // It would be nice to remove an empty buffer at the beginning,
00908   // but this breaks HTTP.
00909   // if (!_writer || !_writer->read_avail())
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 //  MIOBuffer::append_block()
00937 //
00938 //  Allocate a block, appends it to current->next
00939 //  and make the new block the current block (writer).
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 //  MIOBuffer::current_write_avail()
00978 //
00979 //  returns the total space available in all blocks.
00980 //  This function is different than write_avail() because
00981 //  it will not append a new block if there is no space
00982 //  or below the watermark space available.
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 //  MIOBuffer::write_avail()
01000 //
01001 //  returns the number of bytes available in the current block.
01002 //  If there is no current block or not enough free space in
01003 //  the current block then a new block is appended.
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

Generated by  doxygen 1.7.1