270 else |
270 else |
271 { |
271 { |
272 len = Min(aLen, len); |
272 len = Min(aLen, len); |
273 } |
273 } |
274 |
274 |
275 TInt err = newChain.Alloc(len + aHdrReserve, *this); |
275 // Suppress the "follow-the-leader" behaviour of preserving the buffer sizing of the |
|
276 // existing chain. The goal of preserving buffer characteristics remains desirable but |
|
277 // not at the cost of having TCP use unnecessarily small buffers - this area needs |
|
278 // rework once the Comms stack really adopts buffer pools and zero copy |
|
279 // TInt err = newChain.Alloc(len + aHdrReserve, *this); |
|
280 TInt err; |
|
281 if(First()) |
|
282 { |
|
283 newChain.iNext = First()->Pool()->Pond().Alloc(len + aHdrReserve, 0, KMaxTInt); |
|
284 err = iNext ? KErrNone : KErrNoMBufs; |
|
285 } |
|
286 else |
|
287 { |
|
288 RMBufAllocator allocator; |
|
289 err = newChain.Alloc(aLen + aHdrReserve, allocator); |
|
290 } |
|
291 |
276 if(err != KErrNone) |
292 if(err != KErrNone) |
277 { |
293 { |
278 return err; |
294 return err; |
279 } |
295 } |
280 |
296 |
530 newChain gets the other half. |
546 newChain gets the other half. |
531 @param anOffset The offset |
547 @param anOffset The offset |
532 @param newChain The result chain |
548 @param newChain The result chain |
533 */ |
549 */ |
534 { |
550 { |
535 User::LeaveIfError(RCommsBufChain::Split(anOffset, newChain)); |
551 User::LeaveIfError(Split(anOffset, newChain)); |
536 } |
552 } |
537 |
553 |
538 EXPORT_C TInt RMBufChain::Split(TInt anOffset, RMBufChain& newChain) |
554 EXPORT_C TInt RMBufChain::Split(TInt aOffset, RMBufChain& aNewChain) |
539 /** |
555 /** |
540 Split a chain into two new chains Original chain gets the 1st half |
556 Split a chain into two new chains Original chain gets the 1st half |
541 newChain gets the other half. |
557 newChain gets the other half. |
542 - refer RMBufChain::AllocL notes regarding the deliberate decision not to provide an overloaded min/max mbuf size variant |
558 - refer RMBufChain::AllocL notes regarding the deliberate decision not to provide an overloaded min/max mbuf size variant |
543 @param anOffset The offset |
559 @param anOffset The offset |
544 @param newChain The result chain |
560 @param newChain The result chain |
545 */ |
561 */ |
546 { |
562 { |
547 return RCommsBufChain::Split(anOffset, newChain); |
563 // RCommsBuf::Split() will not allocate a smaller buffer size than the current, as part of its approach of (trying to) |
548 } |
564 // support zero-copy transfer by respecting the buffer pool in use. This work is incomplete (needs support throughout |
|
565 // the stack and probably a cleverer idea of what constitutes an acceptable buffer than simply size), so in the meantime |
|
566 // having MBufMgr reflect this behaviour by refusing to Split() a big buf into smaller bufs is unnecessarily purist. |
|
567 // Hence the functionality is implemented directly here |
|
568 |
|
569 __ASSERT_ALWAYS(iNext!=NULL, CommsBuf::Panic(EMBuf_EmptyChain)); |
|
570 __ASSERT_ALWAYS(aOffset>=0, CommsBuf::Panic(EMBuf_NegativeOffset)); |
|
571 |
|
572 // For testing post-conditions |
|
573 #ifdef _DEBUG |
|
574 TInt origLen = Length(); |
|
575 #endif |
|
576 TInt splitBufOffset; |
|
577 TInt splitBufRemainder; |
|
578 RMBuf* splitBuf; |
|
579 RMBuf* splitBufPrev; |
|
580 |
|
581 if(!Goto(aOffset, splitBuf, splitBufOffset, splitBufRemainder, splitBufPrev)) |
|
582 { |
|
583 aNewChain.Init(); |
|
584 return KErrNone; |
|
585 } |
|
586 |
|
587 if(splitBufOffset != splitBuf->Offset()) // Not on an mbuf boundary |
|
588 { |
|
589 // Copy tail of splitBuf out to a new chain (hopefully a single buf, but needn't be) |
|
590 TInt splitDataOffset = splitBufOffset - splitBuf->Offset(); |
|
591 TInt err = RMBufChain(splitBuf).Copy(aNewChain, splitDataOffset, splitBufRemainder); |
|
592 if(err != KErrNone) |
|
593 { |
|
594 return err; |
|
595 } |
|
596 splitBuf->AdjustDataEnd(-splitBufRemainder); |
|
597 RMBufChain splitTail(splitBuf->Next()); |
|
598 aNewChain.Append(splitTail); |
|
599 splitBuf->SetNext(NULL); |
|
600 } |
|
601 else |
|
602 { |
|
603 // Split cleaves chain between bufs |
|
604 aNewChain = splitBuf; |
|
605 if(splitBufPrev) |
|
606 { |
|
607 splitBufPrev->Unlink(); |
|
608 } |
|
609 } |
|
610 |
|
611 // Check post-conditions |
|
612 #ifdef _DEBUG |
|
613 TInt frag1Len = Length(); |
|
614 TInt frag2Len = aNewChain.Length(); |
|
615 ASSERT(origLen == frag1Len + frag2Len); |
|
616 ASSERT(frag1Len == aOffset); |
|
617 #endif |
|
618 return KErrNone; |
|
619 } |
549 |
620 |
550 // overloading for TLS |
621 // overloading for TLS |
551 EXPORT_C TInt RMBufChain::Split(TInt anOffset, RMBufChain& newChain, RMBufAllocator& /* aRMBufAllocator */) |
622 EXPORT_C TInt RMBufChain::Split(TInt anOffset, RMBufChain& newChain, RMBufAllocator& /* aRMBufAllocator */) |
552 { |
623 { |
553 return RCommsBufChain::Split ( anOffset, newChain ); |
624 return RCommsBufChain::Split ( anOffset, newChain ); |