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 
00027 
00028 
00029 
00030 
00031 
00032 
00033 #include "libts.h"
00034 #include "HdrHeap.h"
00035 #include "URL.h"
00036 #include "MIME.h"
00037 #include "HTTP.h"
00038 #include "I_EventSystem.h"
00039 
00040 #define MAX_LOST_STR_SPACE 1024
00041 
00042 Allocator hdrHeapAllocator("hdrHeap", HDR_HEAP_DEFAULT_SIZE);
00043 static HdrHeap proto_heap;
00044 
00045 Allocator strHeapAllocator("hdrStrHeap", HDR_STR_HEAP_DEFAULT_SIZE);
00046 static HdrStrHeap str_proto_heap;
00047 
00048 
00049 
00050 
00051 void
00052 obj_describe(HdrHeapObjImpl * obj, bool recurse)
00053 {
00054   static const char *obj_names[] = { "EMPTY", "RAW", "URL", "HTTP_HEADER", "MIME_HEADER", "FIELD_BLOCK" };
00055 
00056   Debug("http", "%s %p: [T: %d, L: %4d, OBJFLAGS: %X]  ",
00057         obj_names[obj->m_type], obj, obj->m_type, obj->m_length, obj->m_obj_flags);
00058 
00059   extern void url_describe(HdrHeapObjImpl * obj, bool recurse);
00060   extern void http_hdr_describe(HdrHeapObjImpl * obj, bool recurse);
00061   extern void mime_hdr_describe(HdrHeapObjImpl * obj, bool recurse);
00062   extern void mime_field_block_describe(HdrHeapObjImpl * obj, bool recurse);
00063 
00064   switch (obj->m_type) {
00065   case HDR_HEAP_OBJ_EMPTY:
00066     break;
00067   case HDR_HEAP_OBJ_RAW:
00068     break;
00069   case HDR_HEAP_OBJ_MIME_HEADER:
00070     mime_hdr_describe(obj, recurse);
00071     break;
00072   case HDR_HEAP_OBJ_FIELD_BLOCK:
00073     mime_field_block_describe(obj, recurse);
00074     break;
00075   case HDR_HEAP_OBJ_HTTP_HEADER:
00076     http_hdr_describe(obj, recurse);
00077     break;
00078   case HDR_HEAP_OBJ_URL:
00079     url_describe(obj, recurse);
00080     break;
00081   default:
00082     break;
00083   }
00084 }
00085 
00086 
00087 
00088 
00089 inline void
00090 HdrHeap::init()
00091 {
00092   m_data_start = m_free_start = ((char *) this) + HDR_HEAP_HDR_SIZE;
00093   m_magic = HDR_BUF_MAGIC_ALIVE;
00094   m_writeable = true;
00095 
00096   m_next = NULL;
00097   m_free_size = m_size - HDR_HEAP_HDR_SIZE;
00098 
00099   
00100   
00101   
00102   m_read_write_heap.m_ptr = NULL;
00103 
00104   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; i++) {
00105     m_ronly_heap[i].m_heap_start = NULL;
00106     m_ronly_heap[i].m_ref_count_ptr.m_ptr = NULL;
00107     m_ronly_heap[i].m_locked = false;
00108     m_ronly_heap[i].m_heap_len = 0;
00109   }
00110   m_lost_string_space = 0;
00111 
00112   ink_assert(m_free_size > 0);
00113 }
00114 
00115 HdrHeap *
00116 new_HdrHeap(int size)
00117 {
00118   HdrHeap *h;
00119   if (size <= HDR_HEAP_DEFAULT_SIZE) {
00120     size = HDR_HEAP_DEFAULT_SIZE;
00121     h = (HdrHeap *)(THREAD_ALLOC(hdrHeapAllocator, this_ethread()));
00122   } else {
00123     h = (HdrHeap *)ats_malloc(size);
00124   }
00125 
00126 
00127 
00128   
00129   *((void **) h) = *((void **) &proto_heap);
00130 
00131   h->m_size = size;
00132   h->init();
00133 
00134 
00135   return h;
00136 }
00137 
00138 HdrStrHeap *
00139 new_HdrStrHeap(int requested_size)
00140 {
00141   
00142   
00143   
00144   
00145 
00146   int alloc_size = requested_size + sizeof(HdrStrHeap);
00147 
00148   HdrStrHeap *sh;
00149   if (alloc_size <= HDR_STR_HEAP_DEFAULT_SIZE) {
00150     alloc_size = HDR_STR_HEAP_DEFAULT_SIZE;
00151     sh = (HdrStrHeap *)(THREAD_ALLOC(strHeapAllocator, this_ethread()));
00152   } else {
00153     alloc_size = ROUND(alloc_size, HDR_STR_HEAP_DEFAULT_SIZE*2);
00154     sh = (HdrStrHeap *)ats_malloc(alloc_size);
00155   }
00156 
00157 
00158 
00159   
00160   *((void **) sh) = *((void **) &str_proto_heap);
00161 
00162   sh->m_heap_size = alloc_size;
00163   sh->m_free_size = alloc_size - STR_HEAP_HDR_SIZE;
00164   sh->m_free_start = ((char *) sh) + STR_HEAP_HDR_SIZE;
00165   sh->m_refcount = 0;
00166 
00167   ink_assert(sh->m_free_size > 0);
00168 
00169   return sh;
00170 }
00171 
00172 void
00173 HdrHeap::destroy()
00174 {
00175   if (m_next) {
00176     m_next->destroy();
00177   }
00178 
00179   m_read_write_heap = NULL;
00180   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; i++)
00181     m_ronly_heap[i].m_ref_count_ptr = NULL;
00182 
00183   if (m_size == HDR_HEAP_DEFAULT_SIZE) {
00184     THREAD_FREE(this, hdrHeapAllocator, this_thread());
00185   } else {
00186     ats_free(this);
00187   }
00188 }
00189 
00190 HdrHeapObjImpl *
00191 HdrHeap::allocate_obj(int nbytes, int type)
00192 {
00193   char *new_space;
00194   HdrHeapObjImpl *obj;
00195 
00196   ink_assert(m_writeable);
00197 
00198   nbytes = ROUND(nbytes, HDR_PTR_SIZE);
00199 
00200   if (nbytes > (int)HDR_MAX_ALLOC_SIZE) {
00201     ink_assert(!"alloc too big");
00202     return NULL;
00203   }
00204 
00205   HdrHeap *h = this;
00206 
00207 
00208   while (1) {
00209     if ((unsigned) nbytes <= (h->m_free_size)) {
00210       new_space = h->m_free_start;
00211       h->m_free_start += nbytes;
00212       h->m_free_size -= nbytes;
00213 
00214       obj = (HdrHeapObjImpl *) new_space;
00215       obj_init_header(obj, type, nbytes, 0);
00216       ink_assert(obj_is_aligned(obj));
00217 
00218       return obj;
00219 
00220     }
00221 
00222     if (h->m_next == NULL) {
00223       
00224       
00225       
00226       
00227       h->m_next = new_HdrHeap(h->m_size * 2);
00228     }
00229 
00230     h = h->m_next;
00231   }
00232 }
00233 
00234 void
00235 HdrHeap::deallocate_obj(HdrHeapObjImpl * obj)
00236 {
00237   ink_assert(m_writeable);
00238   obj->m_type = HDR_HEAP_OBJ_EMPTY;
00239 }
00240 
00241 
00242 char *
00243 HdrHeap::allocate_str(int nbytes)
00244 {
00245   int last_size = 0;
00246   char *new_space = NULL;
00247   ink_assert(m_writeable);
00248 
00249   
00250   
00251   
00252   
00253   
00254   
00255   
00256   
00257   if (m_lost_string_space > (int)MAX_LOST_STR_SPACE) {
00258     goto FAILED;
00259   }
00260 
00261 
00262 RETRY:
00263   
00264   
00265   if (!m_read_write_heap) {
00266     int next_size = (last_size * 2) - STR_HEAP_HDR_SIZE;
00267     next_size = next_size > nbytes ? next_size : nbytes;
00268     m_read_write_heap = new_HdrStrHeap(next_size);
00269   }
00270   
00271   new_space = m_read_write_heap->allocate(nbytes);
00272 
00273   if (new_space) {
00274     return new_space;
00275   }
00276 
00277   last_size = m_read_write_heap->m_heap_size;
00278 
00279   
00280   
00281   
00282   if (demote_rw_str_heap() == 0) {
00283     goto RETRY;
00284   }
00285 
00286 FAILED:
00287   
00288   
00289   coalesce_str_heaps();
00290   goto RETRY;
00291 
00292 }
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 char *
00303 HdrHeap::expand_str(const char *old_str, int old_len, int new_len)
00304 {
00305   if (m_read_write_heap && m_read_write_heap->contains(old_str))
00306     return m_read_write_heap->expand((char *)old_str, old_len, new_len);
00307 
00308   return NULL;
00309 }
00310 
00311 
00312 
00313 
00314 
00315 
00316 char *
00317 HdrHeap::duplicate_str(const char *str, int nbytes)
00318 {
00319   HeapGuard guard(this, str); 
00320   char *new_str = allocate_str(nbytes);
00321 
00322   memcpy(new_str, str, nbytes);
00323   return (new_str);
00324 }
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 int
00334 HdrHeap::demote_rw_str_heap()
00335 {
00336   
00337   
00338   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; i++) {
00339     if (m_ronly_heap[i].m_heap_start == NULL) {
00340       
00341       m_ronly_heap[i].m_ref_count_ptr = m_read_write_heap;
00342       m_ronly_heap[i].m_heap_start = (char *) m_read_write_heap.m_ptr;
00343       m_ronly_heap[i].m_heap_len = m_read_write_heap->m_heap_size - m_read_write_heap->m_free_size;
00344 
00345 
00346       m_read_write_heap = NULL;
00347       return 0;
00348     }
00349   }
00350 
00351   
00352   return 1;
00353 }
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 void
00366 HdrHeap::coalesce_str_heaps(int incoming_size)
00367 {
00368   int new_heap_size = incoming_size;
00369   ink_assert(incoming_size >= 0);
00370   ink_assert(m_writeable);
00371 
00372   new_heap_size += required_space_for_evacuation();
00373 
00374   HdrStrHeap *new_heap = new_HdrStrHeap(new_heap_size);
00375   evacuate_from_str_heaps(new_heap);
00376   m_lost_string_space = 0;
00377 
00378   
00379   
00380   
00381   m_read_write_heap = new_heap;
00382 
00383   int heaps_removed = 0;
00384   for (int j = 0; j < HDR_BUF_RONLY_HEAPS; j++) {
00385     if (m_ronly_heap[j].m_heap_start != NULL && m_ronly_heap[j].m_locked == false) {
00386       m_ronly_heap[j].m_ref_count_ptr = NULL;
00387       m_ronly_heap[j].m_heap_start = NULL;
00388       m_ronly_heap[j].m_heap_len = 0;
00389       heaps_removed++;
00390     }
00391   }
00392 
00393   
00394   
00395   
00396   ink_assert(heaps_removed > 0 || incoming_size > 0 || m_ronly_heap[0].m_heap_start == NULL);
00397 }
00398 
00399 void
00400 HdrHeap::evacuate_from_str_heaps(HdrStrHeap * new_heap)
00401 {
00402 
00403   
00404   
00405   HdrHeap *h = this;
00406   ink_assert(m_writeable);
00407 
00408   while (h) {
00409     char *data = h->m_data_start;
00410 
00411     while (data < h->m_free_start) {
00412       HdrHeapObjImpl *obj = (HdrHeapObjImpl *) data;
00413 
00414       switch (obj->m_type) {
00415       case HDR_HEAP_OBJ_URL:
00416         ((URLImpl *) obj)->move_strings(new_heap);
00417         break;
00418       case HDR_HEAP_OBJ_HTTP_HEADER:
00419         ((HTTPHdrImpl *) obj)->move_strings(new_heap);
00420         break;
00421       case HDR_HEAP_OBJ_MIME_HEADER:
00422         ((MIMEHdrImpl *) obj)->move_strings(new_heap);
00423         break;
00424       case HDR_HEAP_OBJ_FIELD_BLOCK:
00425         ((MIMEFieldBlockImpl *) obj)->move_strings(new_heap);
00426         break;
00427       case HDR_HEAP_OBJ_EMPTY:
00428       case HDR_HEAP_OBJ_RAW:
00429         
00430         break;
00431       default:
00432         ink_release_assert(0);
00433       }
00434 
00435       data = data + obj->m_length;
00436     }
00437 
00438     h = h->m_next;
00439 
00440   }
00441 }
00442 
00443 size_t
00444 HdrHeap::required_space_for_evacuation()
00445 {
00446   size_t ret = 0;
00447   HdrHeap *h = this;
00448   while (h) {
00449     char *data = h->m_data_start;
00450 
00451     while (data < h->m_free_start) {
00452       HdrHeapObjImpl *obj = (HdrHeapObjImpl *) data;
00453 
00454       switch (obj->m_type) {
00455       case HDR_HEAP_OBJ_URL:
00456         ret += ((URLImpl *) obj)->strings_length();
00457         break;
00458       case HDR_HEAP_OBJ_HTTP_HEADER:
00459         ret += ((HTTPHdrImpl *) obj)->strings_length();
00460         break;
00461       case HDR_HEAP_OBJ_MIME_HEADER:
00462         ret += ((MIMEHdrImpl *) obj)->strings_length();
00463         break;
00464       case HDR_HEAP_OBJ_FIELD_BLOCK:
00465         ret += ((MIMEFieldBlockImpl *) obj)->strings_length();
00466         break;
00467       case HDR_HEAP_OBJ_EMPTY:
00468       case HDR_HEAP_OBJ_RAW:
00469         
00470         break;
00471       default:
00472         ink_release_assert(0);
00473       }
00474       data = data + obj->m_length;
00475     }
00476     h = h->m_next;
00477   }
00478   return ret;
00479 }
00480 
00481 void
00482 HdrHeap::sanity_check_strs()
00483 {
00484   int num_heaps = 0;
00485   struct HeapCheck heaps[HDR_BUF_RONLY_HEAPS + 1];
00486 
00487   
00488   if (m_read_write_heap) {
00489     heaps[num_heaps].start = ((char *) m_read_write_heap.m_ptr) + sizeof(HdrStrHeap);
00490 
00491     int heap_size = m_read_write_heap->m_heap_size - (sizeof(HdrStrHeap) + m_read_write_heap->m_free_size);
00492 
00493     heaps[num_heaps].end = heaps[num_heaps].start + heap_size;
00494     num_heaps++;
00495   }
00496 
00497   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; i++) {
00498     if (m_ronly_heap[i].m_heap_start != NULL) {
00499       heaps[num_heaps].start = m_ronly_heap[i].m_heap_start;
00500       heaps[num_heaps].end = m_ronly_heap[i].m_heap_start + m_ronly_heap[i].m_heap_len;
00501       num_heaps++;
00502     }
00503   }
00504 
00505 
00506   
00507   
00508   HdrHeap *h = this;
00509 
00510   while (h) {
00511     char *data = h->m_data_start;
00512 
00513     while (data < h->m_free_start) {
00514       HdrHeapObjImpl *obj = (HdrHeapObjImpl *) data;
00515 
00516       switch (obj->m_type) {
00517       case HDR_HEAP_OBJ_URL:
00518         ((URLImpl *) obj)->check_strings(heaps, num_heaps);
00519         break;
00520       case HDR_HEAP_OBJ_HTTP_HEADER:
00521         ((HTTPHdrImpl *) obj)->check_strings(heaps, num_heaps);
00522         break;
00523       case HDR_HEAP_OBJ_MIME_HEADER:
00524         ((MIMEHdrImpl *) obj)->check_strings(heaps, num_heaps);
00525         break;
00526       case HDR_HEAP_OBJ_FIELD_BLOCK:
00527         ((MIMEFieldBlockImpl *) obj)->check_strings(heaps, num_heaps);
00528         break;
00529       case HDR_HEAP_OBJ_EMPTY:
00530       case HDR_HEAP_OBJ_RAW:
00531         
00532         break;
00533       default:
00534         ink_release_assert(0);
00535       }
00536 
00537       data = data + obj->m_length;
00538     }
00539 
00540     h = h->m_next;
00541 
00542   }
00543 }
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 int
00552 HdrHeap::marshal_length()
00553 {
00554   int len;
00555 
00556   
00557   
00558   
00559   len = HDR_HEAP_HDR_SIZE;
00560   HdrHeap *h = this;
00561 
00562   while (h) {
00563     len += (int) (h->m_free_start - h->m_data_start);
00564     h = h->m_next;
00565   }
00566 
00567   
00568   
00569   
00570   if (m_read_write_heap) {
00571     len += m_read_write_heap->m_heap_size - (sizeof(HdrStrHeap) + m_read_write_heap->m_free_size);
00572   }
00573 
00574   for (int j = 0; j < HDR_BUF_RONLY_HEAPS; j++) {
00575     if (m_ronly_heap[j].m_heap_start != NULL) {
00576       len += m_ronly_heap[j].m_heap_len;
00577     }
00578   }
00579 
00580   len = ROUND(len, HDR_PTR_SIZE);
00581   return len;
00582 }
00583 
00584 #ifdef HDR_HEAP_CHECKSUMS
00585 static uint32_t
00586 compute_checksum(void *buf, int len)
00587 {
00588   uint32_t cksum = 0;
00589 
00590   while (len > 4) {
00591     cksum += *((uint32_t *) buf);
00592     buf = ((char *) buf) + 4;
00593     len -= 4;
00594   }
00595 
00596   if (len > 0) {
00597     uint32_t tmp = 0;
00598     memcpy((char *) &tmp, buf, len);
00599     cksum += tmp;
00600   }
00601 
00602   return cksum;
00603 }
00604 #endif
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 int
00618 HdrHeap::marshal(char *buf, int len)
00619 {
00620   ink_assert((((uintptr_t) buf) & HDR_PTR_ALIGNMENT_MASK) == 0);
00621 
00622   HdrHeap *marshal_hdr = (HdrHeap *) buf;
00623   char *b = buf + HDR_HEAP_HDR_SIZE;
00624 
00625   
00626   int ptr_xl_size = 2;
00627   MarshalXlate static_table[2];
00628   MarshalXlate *ptr_xlation = static_table;
00629 
00630   
00631   
00632   
00633   int ptr_heap_size = 0;
00634   int str_size = 0;
00635   int ptr_heaps = 0;
00636   int str_heaps = 0;
00637 
00638   
00639   
00640   int used;
00641   int i;
00642 
00643   HdrHeap *unmarshal_hdr = this;
00644 
00645   do {
00646     int copy_size = (int) (unmarshal_hdr->m_free_start - unmarshal_hdr->m_data_start);
00647 
00648     if (copy_size > len) {
00649       goto Failed;
00650     }
00651     memcpy(b, unmarshal_hdr->m_data_start, copy_size);
00652 
00653     
00654     if (ptr_heaps >= ptr_xl_size) {
00655       MarshalXlate *tmp_xl = (MarshalXlate *) alloca(sizeof(MarshalXlate) * ptr_xl_size * 2);
00656       memcpy(tmp_xl, ptr_xlation, sizeof(MarshalXlate) * ptr_xl_size);
00657       ptr_xlation = tmp_xl;
00658       ptr_xl_size *= 2;
00659     }
00660     
00661     
00662     ptr_xlation[ptr_heaps].start = unmarshal_hdr->m_data_start;
00663     ptr_xlation[ptr_heaps].end = unmarshal_hdr->m_free_start;
00664     ptr_xlation[ptr_heaps].offset = unmarshal_hdr->m_data_start - (b - buf);
00665 
00666     ptr_heap_size += copy_size;
00667     b += copy_size;
00668     len -= copy_size;
00669     ptr_heaps++;
00670 
00671     unmarshal_hdr = unmarshal_hdr->m_next;
00672   } while (unmarshal_hdr);
00673 
00674   
00675   
00676   marshal_hdr->m_free_start = NULL;
00677   marshal_hdr->m_data_start = (char *) HDR_HEAP_HDR_SIZE;       
00678   marshal_hdr->m_magic = HDR_BUF_MAGIC_MARSHALED;
00679   marshal_hdr->m_writeable = false;
00680   marshal_hdr->m_size = ptr_heap_size + HDR_HEAP_HDR_SIZE;
00681   marshal_hdr->m_next = NULL;
00682   marshal_hdr->m_free_size = 0;
00683   marshal_hdr->m_read_write_heap.m_ptr = NULL;
00684   marshal_hdr->m_lost_string_space = this->m_lost_string_space;
00685 
00686   
00687   marshal_hdr->m_ronly_heap[0].m_heap_start = (char *)(intptr_t)marshal_hdr->m_size;     
00688   marshal_hdr->m_ronly_heap[0].m_ref_count_ptr.m_ptr = NULL;
00689 
00690   for (int i = 1; i < HDR_BUF_RONLY_HEAPS; i++)
00691     marshal_hdr->m_ronly_heap[i].m_heap_start = NULL;
00692 
00693   
00694   
00695   
00696   
00697   
00698   
00699   
00700   
00701   
00702   MarshalXlate str_xlation[HDR_BUF_RONLY_HEAPS + 1];
00703 
00704   if (m_read_write_heap) {
00705     char *copy_start = ((char *) m_read_write_heap.m_ptr) + sizeof(HdrStrHeap);
00706     int nto_copy = m_read_write_heap->m_heap_size - (sizeof(HdrStrHeap) + m_read_write_heap->m_free_size);
00707 
00708     if (nto_copy > len) {
00709       goto Failed;
00710     }
00711 
00712     memcpy(b, copy_start, nto_copy);
00713 
00714     
00715     str_xlation[str_heaps].start = copy_start;
00716     str_xlation[str_heaps].end = copy_start + nto_copy;
00717     str_xlation[str_heaps].offset = copy_start - (b - buf);
00718 
00719     b += nto_copy;
00720     len -= nto_copy;
00721     str_size += nto_copy;
00722     str_heaps++;
00723   }
00724 
00725   for (i = 0; i < HDR_BUF_RONLY_HEAPS; i++) {
00726     if (m_ronly_heap[i].m_heap_start != NULL) {
00727       if (m_ronly_heap[i].m_heap_len > len) {
00728         goto Failed;
00729       }
00730 
00731       memcpy(b, m_ronly_heap[i].m_heap_start, m_ronly_heap[i].m_heap_len);
00732 
00733       
00734       
00735       str_xlation[str_heaps].start = m_ronly_heap[i].m_heap_start;
00736       str_xlation[str_heaps].end = m_ronly_heap[i].m_heap_start + m_ronly_heap[i].m_heap_len;
00737       str_xlation[str_heaps].offset = str_xlation[str_heaps].start - (b - buf);
00738       ink_assert(str_xlation[str_heaps].start <= str_xlation[str_heaps].end);
00739 
00740       str_heaps++;
00741       b += m_ronly_heap[i].m_heap_len;
00742       len -= m_ronly_heap[i].m_heap_len;
00743       str_size += m_ronly_heap[i].m_heap_len;
00744     }
00745   }
00746 
00747   
00748   marshal_hdr->m_ronly_heap[0].m_heap_len = str_size;
00749 
00750   
00751   
00752   
00753   {
00754     char *obj_data = ((char *) marshal_hdr) + HDR_HEAP_HDR_SIZE;
00755     char *mheap_end = ((char *) marshal_hdr) + marshal_hdr->m_size;
00756 
00757     while (obj_data < mheap_end) {
00758       HdrHeapObjImpl *obj = (HdrHeapObjImpl *) obj_data;
00759       ink_assert(obj_is_aligned(obj));
00760 
00761       switch (obj->m_type) {
00762       case HDR_HEAP_OBJ_URL:
00763         if (((URLImpl *) obj)->marshal(str_xlation, str_heaps) < 0) {
00764           goto Failed;
00765         }
00766         break;
00767       case HDR_HEAP_OBJ_HTTP_HEADER:
00768         if (((HTTPHdrImpl *) obj)->marshal(ptr_xlation, ptr_heaps, str_xlation, str_heaps) < 0) {
00769           goto Failed;
00770         }
00771         break;
00772       case HDR_HEAP_OBJ_FIELD_BLOCK:
00773         if (((MIMEFieldBlockImpl *) obj)->marshal(ptr_xlation, ptr_heaps, str_xlation, str_heaps) < 0) {
00774           goto Failed;
00775         }
00776         break;
00777       case HDR_HEAP_OBJ_MIME_HEADER:
00778         if (((MIMEHdrImpl *) obj)->marshal(ptr_xlation, ptr_heaps, str_xlation, str_heaps)) {
00779           goto Failed;
00780         }
00781         break;
00782       case HDR_HEAP_OBJ_EMPTY:
00783       case HDR_HEAP_OBJ_RAW:
00784         
00785         
00786         if (obj->m_length <= 0) {
00787           ink_assert(0);
00788           goto Failed;
00789         }
00790         
00791         break;
00792       default:
00793         ink_release_assert(0);
00794       }
00795 
00796       obj_data = obj_data + obj->m_length;
00797     }
00798   }
00799 
00800   
00801   used = ptr_heap_size + str_size + HDR_HEAP_HDR_SIZE;
00802   used = ROUND(used, HDR_PTR_SIZE);
00803 
00804 #ifdef HDR_HEAP_CHECKSUMS
00805   {
00806     uint32_t chksum = compute_checksum(buf, used);
00807     marshal_hdr->m_free_start = (char *) chksum;
00808   }
00809 #endif
00810 
00811   return used;
00812 
00813 Failed:
00814   marshal_hdr->m_magic = HDR_BUF_MAGIC_CORRUPT;
00815   return -1;
00816 }
00817 
00818 
00819 
00820 
00821 
00822 
00823 
00824 bool
00825 HdrHeap::check_marshalled(uint32_t buf_length)
00826 {
00827   if (this->m_magic != HDR_BUF_MAGIC_MARSHALED) {
00828     return false;
00829   }
00830 
00831   if (this->m_size < (uint32_t) HDR_HEAP_HDR_SIZE) {
00832     return false;
00833   }
00834 
00835   if (this->m_size != (uintptr_t) this->m_ronly_heap[0].m_heap_start) {
00836     return false;
00837   }
00838 
00839   if ((uintptr_t) (this->m_size + m_ronly_heap[0].m_heap_start) > buf_length) {
00840     return false;
00841   }
00842 
00843   if (this->m_writeable != false) {
00844     return false;
00845   }
00846 
00847   if (this->m_free_size != 0) {
00848     return false;
00849   }
00850 
00851   if (this->m_ronly_heap[0].m_heap_start == NULL) {
00852     return false;
00853   }
00854 
00855   return true;
00856 }
00857 
00858 
00859 
00860 
00861 
00862 
00863 
00864 
00865 
00866 
00867 
00868 
00869 
00870 
00871 int
00872 HdrHeap::unmarshal(int buf_length, int obj_type, HdrHeapObjImpl ** found_obj, RefCountObj * block_ref)
00873 {
00874   bool obj_found = false;
00875 
00876   
00877   if (m_magic != HDR_BUF_MAGIC_MARSHALED) {
00878     ink_assert(!"HdrHeap::unmarshal bad magic");
00879     return -1;
00880   }
00881 
00882   int unmarshal_size = this->unmarshal_size();
00883   if (unmarshal_size > buf_length) {
00884     ink_assert(!"HdrHeap::unmarshal truncated header");
00885     return -1;
00886   }
00887 #ifdef HDR_HEAP_CHECKSUMS
00888   if (m_free_start != NULL) {
00889     uint32_t stored_sum = (uint32_t) m_free_start;
00890     m_free_start = NULL;
00891     int sum_len = ROUND(unmarshal_size, HDR_PTR_SIZE);
00892     uint32_t new_sum = compute_checksum((void *) this, sum_len);
00893 
00894     if (stored_sum != new_sum) {
00895       fprintf(stderr, "WARNING: Unmarshal checksum comparison failed\n");
00896       dump_heap(unmarshal_size);
00897       ink_assert(!"HdrHeap::unmarshal checksum failure");
00898       return -1;
00899     }
00900   }
00901 #else
00902   
00903   
00904   
00905   m_free_start = NULL;
00906 #endif
00907 
00908   ink_release_assert(m_writeable == false);
00909   ink_release_assert(m_free_size == 0);
00910   ink_release_assert(m_ronly_heap[0].m_heap_start != NULL);
00911 
00912   ink_assert(m_free_start == NULL);
00913 
00914   
00915   m_data_start = ((char *) this) + (intptr_t) m_data_start;
00916   m_free_start = ((char *) this) + m_size;
00917   m_ronly_heap[0].m_heap_start = ((char *) this) + (intptr_t) m_ronly_heap[0].m_heap_start;
00918 
00919   
00920   
00921   
00922   
00923   
00924   
00925   
00926   
00927   
00928   
00929   if (block_ref) {
00930     m_ronly_heap[0].m_ref_count_ptr.m_ptr = block_ref;
00931   }
00932   
00933   
00934   char *obj_data = m_data_start;
00935   intptr_t offset = (intptr_t) this;
00936 
00937   while (obj_data < m_free_start) {
00938     HdrHeapObjImpl *obj = (HdrHeapObjImpl *) obj_data;
00939     ink_assert(obj_is_aligned(obj));
00940 
00941     if (obj->m_type == (unsigned) obj_type && obj_found == false) {
00942       *found_obj = obj;
00943     }
00944 
00945     switch (obj->m_type) {
00946     case HDR_HEAP_OBJ_HTTP_HEADER:
00947       ((HTTPHdrImpl *) obj)->unmarshal(offset);
00948       break;
00949     case HDR_HEAP_OBJ_URL:
00950       ((URLImpl *) obj)->unmarshal(offset);
00951       break;
00952     case HDR_HEAP_OBJ_FIELD_BLOCK:
00953       ((MIMEFieldBlockImpl *) obj)->unmarshal(offset);
00954       break;
00955     case HDR_HEAP_OBJ_MIME_HEADER:
00956       ((MIMEHdrImpl *) obj)->unmarshal(offset);
00957       break;
00958     case HDR_HEAP_OBJ_EMPTY:
00959       
00960       break;
00961     default:
00962       fprintf(stderr,
00963               "WARNING: Unmarshal failed due to unknow obj type %d after %d bytes",
00964               (int) obj->m_type, (int)(obj_data - (char *) this));
00965       dump_heap(unmarshal_size);
00966       return -1;
00967     }
00968 
00969     obj_data = obj_data + obj->m_length;
00970   }
00971 
00972   m_magic = HDR_BUF_MAGIC_ALIVE;
00973 
00974   unmarshal_size = ROUND(unmarshal_size, HDR_PTR_SIZE);
00975   return unmarshal_size;
00976 }
00977 
00978 inline int
00979 HdrHeap::attach_str_heap(char *h_start, int h_len, RefCountObj * h_ref_obj, int *index)
00980 {
00981   
00982   for (int z = 0; z < *index; z++) {
00983     if (m_ronly_heap[z].m_heap_start == h_start) {
00984       ink_assert(m_ronly_heap[z].m_ref_count_ptr._ptr() == h_ref_obj);
00985 
00986       
00987       
00988       
00989       
00990       if (h_len > m_ronly_heap[z].m_heap_len)
00991         m_ronly_heap[z].m_heap_len = h_len;
00992       return 1;
00993     }
00994   }
00995 
00996   if (*index >= HDR_BUF_RONLY_HEAPS) {
00997     return 0;
00998   }
00999 
01000   m_ronly_heap[*index].m_ref_count_ptr = h_ref_obj;
01001   m_ronly_heap[*index].m_heap_start = h_start;
01002   m_ronly_heap[*index].m_heap_len = h_len;
01003   m_ronly_heap[*index].m_locked = false;
01004   *index = *index + 1;
01005 
01006   return 1;
01007 }
01008 
01009 
01010 
01011 
01012 
01013 
01014 
01015 void
01016 HdrHeap::inherit_string_heaps(const HdrHeap * inherit_from)
01017 {
01018   
01019   if (inherit_from == (const HdrHeap *) this)
01020     return;
01021 
01022   int index, result;
01023   int first_free = HDR_BUF_RONLY_HEAPS; 
01024   int free_slots = 0;
01025   int inherit_str_size = 0;
01026   ink_assert(m_writeable);
01027 
01028   
01029   for (index = 0; index < HDR_BUF_RONLY_HEAPS; index++) {
01030     if (m_ronly_heap[index].m_heap_start == NULL) {
01031       if (first_free == HDR_BUF_RONLY_HEAPS) {
01032         first_free = index;
01033       }
01034       free_slots++;
01035     }
01036   }
01037 
01038   
01039   if (inherit_from->m_read_write_heap) {
01040     free_slots--;
01041     inherit_str_size = inherit_from->m_read_write_heap->m_heap_size;
01042   }
01043   for (index = 0; index < HDR_BUF_RONLY_HEAPS; index++) {
01044     if (inherit_from->m_ronly_heap[index].m_heap_start != NULL) {
01045       free_slots--;
01046       inherit_str_size += inherit_from->m_ronly_heap[index].m_heap_len;
01047     } else {
01048       
01049       
01050       break;
01051     }
01052   }
01053 
01054   
01055   int new_lost_space = m_lost_string_space + inherit_from->m_lost_string_space;
01056 
01057   if (free_slots < 0 || new_lost_space > (int)MAX_LOST_STR_SPACE) {
01058     
01059     
01060     
01061     
01062     
01063     
01064     
01065     
01066     coalesce_str_heaps(inherit_str_size);
01067   } else {
01068     
01069     if (inherit_from->m_read_write_heap) {
01070       int str_size = inherit_from->m_read_write_heap->m_heap_size -
01071         STR_HEAP_HDR_SIZE - inherit_from->m_read_write_heap->m_free_size;
01072       result = attach_str_heap(((char *) inherit_from->m_read_write_heap.m_ptr) + STR_HEAP_HDR_SIZE,
01073                                str_size, inherit_from->m_read_write_heap, &first_free);
01074       ink_release_assert(result != 0);
01075     }
01076     
01077     for (int i = 0; i < HDR_BUF_RONLY_HEAPS; i++) {
01078       if (inherit_from->m_ronly_heap[i].m_heap_start) {
01079         result = attach_str_heap(inherit_from->m_ronly_heap[i].m_heap_start,
01080                                  inherit_from->m_ronly_heap[i].m_heap_len,
01081                                  inherit_from->m_ronly_heap[i].m_ref_count_ptr.m_ptr, &first_free);
01082         ink_release_assert(result != 0);
01083       }
01084     }
01085 
01086     m_lost_string_space += inherit_from->m_lost_string_space;
01087   }
01088 
01089   return;
01090 }
01091 
01092 
01093 
01094 
01095 void
01096 HdrHeap::dump_heap(int len)
01097 {
01098   int count = 0;
01099   char *tmp = (char *) this;
01100   char *end;
01101   uint32_t content;
01102 
01103   if (len < 0) {
01104     len = m_size;
01105   }
01106   end = ((char *) this) + len;
01107 
01108   fprintf(stderr, "---- Dumping header heap @ 0x%" PRIx64 " - len %d ------", (uint64_t) ((ptrdiff_t) this), len);
01109 
01110   while (tmp < end) {
01111     if (count % 4 == 0) {
01112       fprintf(stderr, "\n0x%" PRIx64 ": ", (uint64_t) ((ptrdiff_t) tmp));
01113     }
01114     count++;
01115 
01116     
01117     if (end - tmp > 4) {
01118       content = *((uint32_t *) tmp);
01119     } else {
01120       
01121       
01122       content = 0;
01123       memcpy(&content, tmp, (end - tmp));
01124     }
01125 
01126     fprintf(stderr, "0x%x ", content);
01127     tmp += 4;
01128   }
01129 
01130   fprintf(stderr, "\n-------------- End header heap dump -----------\n");
01131 }
01132 
01133 
01134 void
01135 HdrStrHeap::free()
01136 {
01137   if (m_heap_size == HDR_STR_HEAP_DEFAULT_SIZE) {
01138     THREAD_FREE(this, strHeapAllocator, this_thread());
01139   } else {
01140     ats_free(this);
01141   }
01142 }
01143 
01144 
01145 
01146 
01147 
01148 
01149 char *
01150 HdrStrHeap::allocate(int nbytes)
01151 {
01152   char *new_space;
01153 
01154   if (m_free_size >= (unsigned) nbytes) {
01155     new_space = m_free_start;
01156     m_free_start += nbytes;
01157     m_free_size -= nbytes;
01158     return new_space;
01159   } else {
01160     return NULL;
01161   }
01162 }
01163 
01164 
01165 
01166 
01167 
01168 
01169 char *
01170 HdrStrHeap::expand(char *ptr, int old_size, int new_size)
01171 {
01172   unsigned int expand_size = new_size - old_size;
01173 
01174   ink_assert(ptr >= ((char *) this) + STR_HEAP_HDR_SIZE);
01175   ink_assert(ptr < ((char *) this) + m_heap_size);
01176 
01177   if (ptr + old_size == m_free_start && expand_size <= m_free_size) {
01178     m_free_start += expand_size;
01179     m_free_size -= expand_size;
01180     return ptr;
01181   } else {
01182     return NULL;
01183   }
01184 }
01185 
01186 
01187 
01188 StrHeapDesc::StrHeapDesc()
01189 {
01190   m_heap_start = NULL;
01191   m_heap_len = 0;
01192   m_locked = false;
01193 }
01194 
01195 struct StrTest
01196 {
01197   char *ptr;
01198   int len;
01199 };
01200 
01201 #if TS_HAS_TESTS
01202 #include <ts/TestBox.h>
01203 REGRESSION_TEST(HdrHeap_Coalesce)(RegressionTest* t, int , int*  pstatus) {
01204   *pstatus = REGRESSION_TEST_PASSED;
01205   
01206 
01207 
01208 
01209 
01210   
01211   size_t next_rw_heap_size = HDR_STR_HEAP_DEFAULT_SIZE;
01212   size_t next_required_overflow_size = next_rw_heap_size - STR_HEAP_HDR_SIZE;
01213   char buf[next_required_overflow_size];
01214   for(unsigned int i = 0; i < sizeof(buf); ++i) {
01215     buf[i] = ('a' + (i % 26));
01216   }
01217 
01218   TestBox tb(t, pstatus);
01219   HdrHeap *heap = new_HdrHeap();
01220   URLImpl *url = url_create(heap);
01221 
01222   tb.check(heap->m_read_write_heap.m_ptr == NULL, "Checking that we have no rw heap.");
01223   url_path_set(heap,url, buf, next_required_overflow_size, true);
01224   tb.check(heap->m_read_write_heap->m_free_size == 0, "Checking that we've completely consumed the rw heap");
01225   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; ++i) {
01226     tb.check(heap->m_ronly_heap[i].m_heap_start == (char*)NULL, "Checking ronly_heap[%d] is NULL", i);
01227   }
01228 
01229   
01230   
01231   for (int ronly_heap = 0; ronly_heap < HDR_BUF_RONLY_HEAPS; ++ronly_heap) {
01232     next_rw_heap_size = 2 * heap->m_read_write_heap->m_heap_size;
01233     next_required_overflow_size = next_rw_heap_size - STR_HEAP_HDR_SIZE;
01234     char buf2[next_required_overflow_size];
01235     for(unsigned int i = 0; i < sizeof(buf2); ++i) {
01236       buf2[i] = ('a' + (i % 26));
01237     }
01238 
01239     URLImpl *url2 = url_create(heap);
01240     url_path_set(heap,url2,buf2,next_required_overflow_size, true);
01241 
01242     tb.check(heap->m_read_write_heap->m_heap_size == (uint32_t)next_rw_heap_size, "Checking the current rw heap is %d bytes", (int)next_rw_heap_size);
01243     tb.check(heap->m_read_write_heap->m_free_size == 0, "Checking that we've completely consumed the rw heap");
01244     tb.check(heap->m_ronly_heap[ronly_heap].m_heap_start != NULL, "Checking that we properly demoted the previous rw heap");
01245     for (int i = ronly_heap + 1; i < HDR_BUF_RONLY_HEAPS; ++i) {
01246       tb.check(heap->m_ronly_heap[i].m_heap_start == NULL, "Checking ronly_heap[%d] is NULL", i);
01247     }
01248   }
01249 
01250   
01251   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; ++i) {
01252     tb.check(heap->m_ronly_heap[i].m_heap_start != (char*)NULL, "Pre non-copied string: Checking ronly_heap[%d] is NOT NULL", i);
01253   }
01254 
01255   
01256   
01257   char buf3[next_required_overflow_size];
01258   for(unsigned int i = 0; i < sizeof(buf); ++i) {
01259     buf3[i] = ('a' + (i % 26));
01260   }
01261 
01262   URLImpl *aliased_str_url = url_create(heap);
01263   url_path_set(heap, aliased_str_url, buf3, next_required_overflow_size, false); 
01264   tb.check(aliased_str_url->m_len_path == next_required_overflow_size, "Checking that the aliased string shows having proper length");
01265   tb.check(aliased_str_url->m_ptr_path == buf3, "Checking that the aliased string is correctly pointing at buf");
01266 
01267 
01268   for (int i = 0; i < HDR_BUF_RONLY_HEAPS; ++i) {
01269     tb.check(heap->m_ronly_heap[i].m_heap_start != (char*)NULL, "Post non-copied string: Checking ronly_heap[%d] is NOT NULL", i);
01270   }
01271   tb.check(heap->m_read_write_heap->m_free_size == 0, "Checking that we've completely consumed the rw heap");
01272   tb.check(heap->m_next == NULL, "Checking that we dont have any chained heaps");
01273 
01274   
01275   
01276   
01277   
01278   
01279 
01280 
01281   char *str = heap->allocate_str(1); 
01282   tb.check(str != NULL, "Checking that 1 byte allocated string is not NULL");
01283 
01284   
01285   
01286   tb.check(aliased_str_url->m_len_path == next_required_overflow_size, "Checking that the aliased string shows having proper length");
01287   tb.check(aliased_str_url->m_ptr_path != NULL, "Checking that the aliased string was properly moved during coalsece and evacuation");
01288   tb.check(aliased_str_url->m_ptr_path != buf3, "Checking that the aliased string was properly moved during coalsece and evacuation (not pointing at buf3)");
01289 
01290   
01291   heap->destroy();
01292 }
01293 #endif