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