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

HdrHeap.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    HdrHeap.h
00027 
00028    Description:
00029 
00030 
00031  ****************************************************************************/
00032 
00033 #ifndef _HDR_HEAP_H_
00034 #define _HDR_HEAP_H_
00035 
00036 #include "Ptr.h"
00037 #include "ink_defs.h"
00038 #include "ink_assert.h"
00039 #include "Arena.h"
00040 #include "HdrToken.h"
00041 
00042 // Objects in the heap must currently be aligned to 8 byte boundaries,
00043 // so their (address & HDR_PTR_ALIGNMENT_MASK) == 0
00044 
00045 #define HDR_PTR_SIZE            (sizeof(uint64_t))
00046 #define HDR_PTR_ALIGNMENT_MASK  ((HDR_PTR_SIZE) - 1L)
00047 
00048 #define ROUND(x,l)  (((x) + ((l) - 1L)) & ~((l) - 1L))
00049 
00050 // A many of the operations regarding read-only str
00051 //  heaps are hand unrolled in the code.  Chaning
00052 //  this value requires a full pass through HdrBuf.cc
00053 //  to fix the unrolled operations
00054 #define HDR_BUF_RONLY_HEAPS   3 
00055 
00056 #define HDR_HEAP_DEFAULT_SIZE   2048
00057 #define HDR_STR_HEAP_DEFAULT_SIZE  2048 
00058 
00059 #define HDR_MAX_ALLOC_SIZE (HDR_HEAP_DEFAULT_SIZE - sizeof(HdrHeap))
00060 #define HDR_HEAP_HDR_SIZE ROUND(sizeof(HdrHeap), HDR_PTR_SIZE)
00061 #define STR_HEAP_HDR_SIZE sizeof(HdrStrHeap)
00062 
00063 enum
00064 {
00065   HDR_HEAP_OBJ_EMPTY = 0,
00066   HDR_HEAP_OBJ_RAW = 1,
00067   HDR_HEAP_OBJ_URL = 2,
00068   HDR_HEAP_OBJ_HTTP_HEADER = 3,
00069   HDR_HEAP_OBJ_MIME_HEADER = 4,
00070   HDR_HEAP_OBJ_FIELD_BLOCK = 5,
00071   HDR_HEAP_OBJ_FIELD_STANDALONE = 6,    // not a type that lives in HdrHeaps
00072   HDR_HEAP_OBJ_FIELD_SDK_HANDLE = 7,    // not a type that lives in HdrHeaps
00073 
00074   HDR_HEAP_OBJ_MAGIC = 0x0FEEB1E0
00075 };
00076 
00077 struct HdrHeapObjImpl
00078 {
00079   uint32_t m_type:8;
00080   uint32_t m_length:20;
00081   uint32_t m_obj_flags:4;
00082 };
00083 
00084 /*-------------------------------------------------------------------------
00085   -------------------------------------------------------------------------*/
00086 
00087 extern void obj_describe(HdrHeapObjImpl * obj, bool recurse);
00088 
00089 inline int
00090 obj_is_aligned(HdrHeapObjImpl * obj)
00091 {
00092   return (((((uintptr_t) obj) & HDR_PTR_ALIGNMENT_MASK) == 0) && ((obj->m_length & HDR_PTR_ALIGNMENT_MASK) == 0));
00093 }
00094 
00095 inline void
00096 obj_clear_data(HdrHeapObjImpl * obj)
00097 {
00098   char *ptr = (char *) obj;
00099   int hdr_length = sizeof(HdrHeapObjImpl);
00100   memset(ptr + hdr_length, '\0', obj->m_length - hdr_length);
00101 }
00102 
00103 inline void
00104 obj_copy_data(HdrHeapObjImpl * s_obj, HdrHeapObjImpl * d_obj)
00105 {
00106   char *src, *dst;
00107 
00108   ink_assert((s_obj->m_length == d_obj->m_length) && (s_obj->m_type == d_obj->m_type));
00109 
00110   int hdr_length = sizeof(HdrHeapObjImpl);
00111   src = (char *) s_obj + hdr_length;
00112   dst = (char *) d_obj + hdr_length;
00113   memcpy(dst, src, d_obj->m_length - hdr_length);
00114 }
00115 
00116 inline void
00117 obj_copy(HdrHeapObjImpl * s_obj, char *d_addr)
00118 {
00119   memcpy(d_addr, (char *) s_obj, s_obj->m_length);
00120 }
00121 
00122 inline void
00123 obj_init_header(HdrHeapObjImpl * obj, uint32_t type, uint32_t nbytes, uint32_t obj_flags)
00124 {
00125   obj->m_type = type;
00126   obj->m_length = nbytes;
00127   obj->m_obj_flags = obj_flags;
00128 }
00129 
00130 /*-------------------------------------------------------------------------
00131   -------------------------------------------------------------------------*/
00132 
00133 enum
00134 {
00135   HDR_BUF_MAGIC_ALIVE = 0xabcdfeed,
00136   HDR_BUF_MAGIC_MARSHALED = 0xdcbafeed,
00137   HDR_BUF_MAGIC_DEAD = 0xabcddead,
00138   HDR_BUF_MAGIC_CORRUPT = 0xbadbadcc
00139 };
00140 
00141 struct StrHeapDesc
00142 {
00143   StrHeapDesc();
00144   Ptr<RefCountObj> m_ref_count_ptr;
00145   char *m_heap_start;
00146   int32_t m_heap_len;
00147   bool m_locked;
00148 
00149   bool contains(const char *str) const
00150   {
00151     return (str >= m_heap_start && str < (m_heap_start + m_heap_len));
00152   }
00153 };
00154 
00155 
00156 class IOBufferBlock;
00157 
00158 class HdrStrHeap:public RefCountObj
00159 {
00160 public:
00161 
00162   virtual void free();
00163 
00164   char *allocate(int nbytes);
00165   char *expand(char *ptr, int old_size, int new_size);
00166   int space_avail();
00167 
00168   uint32_t m_heap_size;
00169   char *m_free_start;
00170   uint32_t m_free_size;
00171 
00172   bool contains(const char *str) const
00173   {
00174     return (str >= ((const char*)this + STR_HEAP_HDR_SIZE) && str < ((const char*)this + m_heap_size));
00175   }
00176 };
00177 
00178 class CoreUtils;
00179 
00180 class HdrHeap
00181 {
00182   friend class CoreUtils;
00183 public:
00184   void init();
00185   inkcoreapi void destroy();
00186 
00187   // PtrHeap allocation
00188   HdrHeapObjImpl *allocate_obj(int nbytes, int type);
00189   void deallocate_obj(HdrHeapObjImpl * obj);
00190 
00191   // StrHeap allocation
00192   char *allocate_str(int nbytes);
00193   char *expand_str(const char *old_str, int old_len, int new_len);
00194   char *duplicate_str(const char *str, int nbytes);
00195   void free_string(const char *s, int len);
00196 
00197   // Marshalling
00198   inkcoreapi int marshal_length();
00199   inkcoreapi int marshal(char *buf, int length);
00200   int unmarshal(int buf_length, int obj_type, HdrHeapObjImpl ** found_obj, RefCountObj * block_ref);
00201   /// Computes the valid data size of an unmarshalled instance.
00202   /// Callers should round up to HDR_PTR_SIZE to get the actual footprint.
00203   int unmarshal_size() const; // TBD - change this name, it's confusing.
00204   // One option - overload marshal_length to return this value if @a magic is HDR_BUF_MAGIC_MARSHALED.
00205 
00206   void inherit_string_heaps(const HdrHeap * inherit_from);
00207   int attach_block(IOBufferBlock * b, const char *use_start);
00208   void set_ronly_str_heap_end(int slot, const char *end);
00209 
00210   // Lock read only str heaps so that can't be moved around
00211   //  by a heap consolidation.  Does NOT lock for Multi-Threaed
00212   //  access!
00213   void lock_ronly_str_heap(int i)
00214   {
00215     m_ronly_heap[i].m_locked = true;
00216   };
00217   void unlock_ronly_str_heap(int i)
00218   {
00219     m_ronly_heap[i].m_locked = false;
00220     // INKqa11238
00221     // Move slot i to the first available slot in m_ronly_heap[].
00222     // The move is necessary because the rest of the code assumes
00223     // heaps are always allocated in order.
00224     for (int j = 0; j < i; j++) {
00225       if (m_ronly_heap[j].m_heap_start == NULL) {
00226         // move slot i to slot j
00227         m_ronly_heap[j].m_ref_count_ptr = m_ronly_heap[i].m_ref_count_ptr;
00228         m_ronly_heap[j].m_heap_start = m_ronly_heap[i].m_heap_start;
00229         m_ronly_heap[j].m_heap_len = m_ronly_heap[i].m_heap_len;
00230         m_ronly_heap[j].m_locked = m_ronly_heap[i].m_locked;
00231         m_ronly_heap[i].m_ref_count_ptr = NULL;
00232         m_ronly_heap[i].m_heap_start = NULL;
00233         m_ronly_heap[i].m_heap_len = 0;
00234         m_ronly_heap[i].m_locked = false;
00235       }
00236     }
00237   };
00238 
00239   // Sanity Check Functions
00240   void sanity_check_strs();
00241   bool check_marshalled(uint32_t buf_length);
00242 
00243   // Debugging functions
00244   void dump_heap(int len = -1);
00245 
00246   uint32_t m_magic;
00247   char *m_free_start;
00248   char *m_data_start;
00249   uint32_t m_size;
00250 
00251   bool m_writeable;
00252 
00253   // Overflow block ptr
00254   //   Overflow blocks are necessary because we can
00255   //     run out of space in the header heap and the
00256   //     heap is not rellocatable
00257   //   Overflow blocks have the HdrHeap full structure
00258   //    header on them, although only first block can
00259   //    point to string heaps
00260   HdrHeap *m_next;
00261 
00262   // HdrBuf heap pointers
00263   uint32_t m_free_size;
00264 
00265   int demote_rw_str_heap();
00266   void coalesce_str_heaps(int incoming_size = 0);
00267   void evacuate_from_str_heaps(HdrStrHeap * new_heap);
00268   size_t required_space_for_evacuation();
00269   int attach_str_heap(char *h_start, int h_len, RefCountObj * h_ref_obj, int *index);
00270 
00271   /** Struct to prevent garbage collection on heaps.
00272       This bumps the reference count to the heap containing the pointer
00273       while the instance of this class exists. When it goes out of scope
00274       the reference is dropped. This is useful inside a method or block
00275       to keep the required heap data around until leaving the scope.
00276   */
00277   struct HeapGuard {
00278     /// Construct the protection.
00279     HeapGuard(HdrHeap* heap, const char *str)
00280     {
00281       if (heap->m_read_write_heap && heap->m_read_write_heap->contains(str)) {
00282         m_ptr = heap->m_read_write_heap;
00283       } else {
00284         for (int i=0; i < HDR_BUF_RONLY_HEAPS; ++i) {
00285           if (heap->m_ronly_heap[i].contains(str)) {
00286             m_ptr = heap->m_ronly_heap[i].m_ref_count_ptr;
00287             break;
00288           }
00289         }
00290       }
00291     }
00292 
00293     // There's no need to have a destructor here, the default dtor will take care of
00294     // releaseing the (potentially) locked heap.
00295 
00296     /// The heap we protect (if any)
00297     Ptr<RefCountObj> m_ptr;
00298   };
00299 
00300   // String Heap access
00301   Ptr<HdrStrHeap> m_read_write_heap;
00302   StrHeapDesc m_ronly_heap[HDR_BUF_RONLY_HEAPS];
00303   int m_lost_string_space;
00304 };
00305 
00306 inline void
00307 HdrHeap::free_string(const char *s, int len)
00308 {
00309   if (s && len > 0) {
00310     m_lost_string_space += len;
00311   }
00312 }
00313 
00314 inline int
00315 HdrHeap::unmarshal_size() const {
00316   return m_size + m_ronly_heap[0].m_heap_len;
00317 }
00318 
00319 
00320 //
00321 struct MarshalXlate
00322 {
00323   char *start;
00324   char *end;
00325   char *offset;
00326 };
00327 
00328 struct HeapCheck
00329 {
00330   char *start;
00331   char *end;
00332 };
00333 
00334 
00335 // Nasty macro to do string marshalling
00336 #define HDR_MARSHAL_STR(ptr, table, nentries) \
00337 if (ptr) { \
00338    int found = 0; \
00339    for (int i = 0; i < nentries; i++) { \
00340       if (ptr >= table[i].start && \
00341           ptr <= table[i].end) { \
00342           ptr =  (((char*)ptr) - (uintptr_t) table[i].offset); \
00343           found = 1; \
00344           break; \
00345       } \
00346    } \
00347    ink_assert(found); \
00348    if (found == 0) { \
00349      return -1; \
00350    } \
00351 }
00352 
00353 // Nasty macro to do string marshalling
00354 #define HDR_MARSHAL_STR_1(ptr, table) \
00355 if (ptr) { \
00356    int found = 0; \
00357       if (ptr >= table[0].start && \
00358           ptr <= table[0].end) { \
00359           ptr =  (((char*)ptr) - (uintptr_t) table[0].offset); \
00360           found = 1; \
00361       } \
00362    ink_assert(found); \
00363    if (found == 0) { \
00364      return -1; \
00365    } \
00366 }
00367 
00368 
00369 
00370 #define HDR_MARSHAL_PTR(ptr, type, table, nentries) \
00371 if (ptr) { \
00372    int found = 0; \
00373    for (int i = 0; i < nentries; i++) { \
00374       if ((char*) ptr >= table[i].start && \
00375           (char*) ptr <= table[i].end) { \
00376           ptr = (type *) (((char*)ptr) - (uintptr_t) table[i].offset); \
00377           found = 1; \
00378           break; \
00379       } \
00380    } \
00381    ink_assert(found); \
00382    if (found == 0) { \
00383     return -1; \
00384    } \
00385 }
00386 
00387 #define HDR_MARSHAL_PTR_1(ptr, type, table) \
00388 if (ptr) { \
00389    int found = 0; \
00390       if ((char*) ptr >= table[0].start && \
00391           (char*) ptr <= table[0].end) { \
00392           ptr = (type *) (((char*)ptr) - (uintptr_t) table[0].offset); \
00393           found = 1; \
00394       } \
00395    ink_assert(found); \
00396    if (found == 0) { \
00397     return -1; \
00398    } \
00399 }
00400 
00401 
00402 
00403 
00404 #define HDR_UNMARSHAL_STR(ptr, offset) \
00405 if (ptr) { \
00406   ptr = ((char*)ptr) + offset; \
00407 }
00408 
00409 #define HDR_UNMARSHAL_PTR(ptr, type, offset) \
00410 if (ptr) { \
00411   ptr = (type *) (((char*)ptr) + offset); \
00412 }
00413 
00414 // Nasty macro to do string evacuation.  Assumes
00415 //   new heap = new_heap
00416 #define HDR_MOVE_STR(str, len) \
00417 { \
00418    if (str) { \
00419      char* new_str = new_heap->allocate(len); \
00420      if(new_str) \
00421        memcpy(new_str, str, len); \
00422      str = new_str; \
00423    } \
00424 }
00425 
00426 // Nasty macro to do verify all strings it
00427 //   in attached heaps
00428 #define CHECK_STR(str, len, _heaps, _num_heaps) \
00429 { \
00430    if (str) { \
00431      int found = 0; \
00432      for (int i = 0; i < _num_heaps; i++) { \
00433         if (str >= _heaps[i].start && \
00434             str + len <= heaps[i].end) { \
00435             found = 1; \
00436         } \
00437      } \
00438      ink_release_assert(found); \
00439    } \
00440 }
00441 
00442 // struct HdrHeapSDKHandle()
00443 //
00444 //   Handle to a HdrHeap.
00445 //
00446 //   Intended to be subclassed and contain a
00447 //     object pointer that points into the heap
00448 //
00449 struct HdrHeapSDKHandle
00450 {
00451 public:
00452   HdrHeapSDKHandle()
00453     : m_heap(NULL)
00454   { }
00455 
00456   ~HdrHeapSDKHandle() { clear(); }
00457 
00458   // clear() only deallocates chained SDK return values
00459   //   The underlying MBuffer is left untouched
00460   void clear();
00461 
00462   // destroy() frees the underlying MBuffer and deallocates all chained
00463   //    SDK return values
00464   void destroy();
00465 
00466   void set(const HdrHeapSDKHandle * from);
00467   const char *make_sdk_string(const char *raw_str, int raw_str_len);
00468 
00469   HdrHeap *m_heap;
00470 
00471 private:
00472   // In order to prevent gratitous refcounting,
00473   //  automatic C++ copies are disabled!
00474     HdrHeapSDKHandle(const HdrHeapSDKHandle & r);
00475     HdrHeapSDKHandle & operator =(const HdrHeapSDKHandle & r);
00476 };
00477 
00478 inline void
00479 HdrHeapSDKHandle::destroy()
00480 {
00481   if (m_heap) {
00482     m_heap->destroy();
00483   }
00484   clear();
00485 }
00486 
00487 inline void
00488 HdrHeapSDKHandle::clear()
00489 {
00490   m_heap = NULL;
00491 }
00492 
00493 inline void
00494 HdrHeapSDKHandle::set(const HdrHeapSDKHandle * from)
00495 {
00496   clear();
00497   m_heap = from->m_heap;
00498 }
00499 
00500 inkcoreapi HdrHeap *new_HdrHeap(int size = HDR_HEAP_DEFAULT_SIZE);
00501 
00502 void hdr_heap_test();
00503 #endif

Generated by  doxygen 1.7.1