* Applied most parts of Adrian's patch in #2594, applied our coding style.

* Cleaned the net_buffer::sequence handling, and fixed a few more problems of
  maintaining it in Add().
* Extended Verify() to check everything that's possible, and call it
  conditionally on several places, depending on DEBUG_BUFFER_QUEUE. It's turned
  on for now which means that any remaining problems should show up when they
  happened.
* Call Dump() from TCPEndpoint::Dump().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28878 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2009-01-11 11:47:31 +00:00
parent f1ee5448a9
commit b3cb15e21e
3 changed files with 115 additions and 10 deletions

View File

@ -19,6 +19,12 @@
# define TRACE(x) # define TRACE(x)
#endif #endif
#if DEBUG_BUFFER_QUEUE
# define VERIFY() Verify();
#else
# define VERIFY() ;
#endif
BufferQueue::BufferQueue(size_t maxBytes) BufferQueue::BufferQueue(size_t maxBytes)
: :
@ -73,13 +79,20 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
TRACE(("BufferQueue@%p::Add(buffer %p, size %lu, sequence %lu)\n", TRACE(("BufferQueue@%p::Add(buffer %p, size %lu, sequence %lu)\n",
this, buffer, buffer->size, (uint32)sequence)); this, buffer, buffer->size, (uint32)sequence));
TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n", TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes)); (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes,
fContiguousBytes));
VERIFY();
buffer->sequence = sequence; if (tcp_sequence(sequence + buffer->size) <= fFirstSequence) {
// This buffer does not contain any data of interest
gBufferModule->free(buffer);
return;
}
if (fList.IsEmpty() || sequence >= fLastSequence) { if (fList.IsEmpty() || sequence >= fLastSequence) {
// we usually just add the buffer to the end of the queue // we usually just add the buffer to the end of the queue
fList.Add(buffer); fList.Add(buffer);
buffer->sequence = sequence;
if (sequence == fLastSequence if (sequence == fLastSequence
&& fLastSequence - fFirstSequence == fNumBytes) { && fLastSequence - fFirstSequence == fNumBytes) {
@ -92,7 +105,9 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
fNumBytes += buffer->size; fNumBytes += buffer->size;
TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n", TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes)); (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes,
fContiguousBytes));
VERIFY();
return; return;
} }
@ -130,22 +145,33 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
buffer = NULL; buffer = NULL;
} else { } else {
fList.Remove(previous); fList.Remove(previous);
fNumBytes -= previous->size;
gBufferModule->free(previous); gBufferModule->free(previous);
} }
} else if (tcp_sequence(previous->sequence + previous->size) > sequence) { } else if (tcp_sequence(previous->sequence + previous->size)
> sequence + buffer->size) {
// We already know this data
gBufferModule->free(buffer);
buffer = NULL;
} else if (tcp_sequence(previous->sequence + previous->size)
> sequence) {
// We already have the first part of this buffer
gBufferModule->remove_header(buffer, gBufferModule->remove_header(buffer,
previous->sequence + previous->size - sequence); previous->sequence + previous->size - sequence);
sequence = previous->sequence + previous->size;
} }
} }
if (buffer != NULL && next != NULL while (buffer != NULL && next != NULL
&& tcp_sequence(sequence + buffer->size) > next->sequence) { && tcp_sequence(sequence + buffer->size) > next->sequence) {
// we already have at least part of this data // we already have at least part of this data
if (tcp_sequence(next->sequence + next->size) < sequence + buffer->size) { if (tcp_sequence(next->sequence + next->size)
< sequence + buffer->size) {
net_buffer *remove = next; net_buffer *remove = next;
next = (net_buffer *)next->link.next; next = (net_buffer *)next->link.next;
fList.Remove(remove); fList.Remove(remove);
fNumBytes -= remove->size;
gBufferModule->free(remove); gBufferModule->free(remove);
} else { } else {
gBufferModule->remove_trailer(buffer, gBufferModule->remove_trailer(buffer,
@ -155,11 +181,14 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
if (buffer == NULL) { if (buffer == NULL) {
TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n", TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes)); (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes,
fContiguousBytes));
VERIFY();
return; return;
} }
fList.Insert(next, buffer); fList.Insert(next, buffer);
buffer->sequence = sequence;
fNumBytes += buffer->size; fNumBytes += buffer->size;
// we might need to update the number of bytes available // we might need to update the number of bytes available
@ -180,6 +209,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n", TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n",
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes)); (uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
VERIFY();
} }
@ -192,6 +222,7 @@ status_t
BufferQueue::RemoveUntil(tcp_sequence sequence) BufferQueue::RemoveUntil(tcp_sequence sequence)
{ {
TRACE(("BufferQueue@%p::RemoveUntil(sequence %lu)\n", this, (uint32)sequence)); TRACE(("BufferQueue@%p::RemoveUntil(sequence %lu)\n", this, (uint32)sequence));
VERIFY();
if (sequence < fFirstSequence) if (sequence < fFirstSequence)
return B_OK; return B_OK;
@ -229,6 +260,7 @@ BufferQueue::RemoveUntil(tcp_sequence sequence)
else else
fFirstSequence = fList.Head()->sequence; fFirstSequence = fList.Head()->sequence;
VERIFY();
return B_OK; return B_OK;
} }
@ -238,7 +270,9 @@ BufferQueue::RemoveUntil(tcp_sequence sequence)
status_t status_t
BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes) BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
{ {
TRACE(("BufferQueue@%p::Get(sequence %lu, bytes %lu)\n", this, (uint32)sequence, bytes)); TRACE(("BufferQueue@%p::Get(sequence %lu, bytes %lu)\n", this,
(uint32)sequence, bytes));
VERIFY();
if (bytes == 0) if (bytes == 0)
return B_OK; return B_OK;
@ -284,6 +318,7 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
source = iterator.Next(); source = iterator.Next();
} }
VERIFY();
return B_OK; return B_OK;
} }
@ -360,10 +395,12 @@ BufferQueue::Get(size_t bytes, bool remove, net_buffer **_buffer)
// We could not remove any bytes from the buffer, so // We could not remove any bytes from the buffer, so
// let this call fail. // let this call fail.
gBufferModule->free(buffer); gBufferModule->free(buffer);
VERIFY();
return status; return status;
} }
*_buffer = buffer; *_buffer = buffer;
VERIFY();
return B_OK; return B_OK;
} }
@ -377,6 +414,7 @@ BufferQueue::Available(tcp_sequence sequence) const
return fContiguousBytes + fFirstSequence - sequence; return fContiguousBytes + fFirstSequence - sequence;
} }
void void
BufferQueue::SetPushPointer() BufferQueue::SetPushPointer()
{ {
@ -385,3 +423,55 @@ BufferQueue::SetPushPointer()
else else
fPushPointer = fList.Tail()->sequence + fList.Tail()->size; fPushPointer = fList.Tail()->sequence + fList.Tail()->size;
} }
#if DEBUG_BUFFER_QUEUE
/*! Perform a sanity check of the whole queue.
*/
void
BufferQueue::Verify() const
{
ASSERT(Available() == 0 || fList.First() != NULL);
if (fList.First() == NULL) {
ASSERT(fNumBytes == 0);
return;
}
SegmentList::ConstIterator iterator = fList.GetIterator();
size_t numBytes = 0;
size_t contiguousBytes = 0;
bool contiguous = true;
tcp_sequence last = fFirstSequence;
while (net_buffer* buffer = iterator.Next()) {
if (contiguous && buffer->sequence == last)
contiguousBytes += buffer->size;
else
contiguous = false;
ASSERT(last <= buffer->sequence);
ASSERT(buffer->size > 0);
numBytes += buffer->size;
last = buffer->sequence + buffer->size;
}
ASSERT(last == fLastSequence);
ASSERT(contiguousBytes == fContiguousBytes);
ASSERT(numBytes == fNumBytes);
}
void
BufferQueue::Dump() const
{
SegmentList::ConstIterator iterator = fList.GetIterator();
int32 number = 0;
while (net_buffer* buffer = iterator.Next()) {
kprintf(" %ld. buffer %p, sequence %lx, size %lu\n", ++number,
buffer, buffer->sequence, buffer->size);
}
}
#endif // DEBUG_BUFFER_QUEUE

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -13,6 +13,10 @@
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#ifndef DEBUG_BUFFER_QUEUE
# define DEBUG_BUFFER_QUEUE 1
#endif
typedef DoublyLinkedList<struct net_buffer, typedef DoublyLinkedList<struct net_buffer,
DoublyLinkedListCLink<struct net_buffer> > SegmentList; DoublyLinkedListCLink<struct net_buffer> > SegmentList;
@ -51,6 +55,11 @@ public:
tcp_sequence NextSequence() const tcp_sequence NextSequence() const
{ return fFirstSequence + fContiguousBytes; } { return fFirstSequence + fContiguousBytes; }
#if DEBUG_BUFFER_QUEUE
void Verify() const;
void Dump() const;
#endif
private: private:
SegmentList fList; SegmentList fList;
size_t fMaxBytes; size_t fMaxBytes;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -2254,6 +2254,9 @@ TCPEndpoint::Dump() const
kprintf(" max window: %lu\n", fSendMaxWindow); kprintf(" max window: %lu\n", fSendMaxWindow);
kprintf(" max segment size: %lu\n", fSendMaxSegmentSize); kprintf(" max segment size: %lu\n", fSendMaxSegmentSize);
kprintf(" queue: %lu / %lu\n", fSendQueue.Used(), fSendQueue.Size()); kprintf(" queue: %lu / %lu\n", fSendQueue.Used(), fSendQueue.Size());
#if DEBUG_BUFFER_QUEUE
fSendQueue.Dump();
#endif
kprintf(" last acknowledge sent: %lu\n", (uint32)fLastAcknowledgeSent); kprintf(" last acknowledge sent: %lu\n", (uint32)fLastAcknowledgeSent);
kprintf(" initial sequence: %lu\n", (uint32)fInitialSendSequence); kprintf(" initial sequence: %lu\n", (uint32)fInitialSendSequence);
kprintf(" receive\n"); kprintf(" receive\n");
@ -2264,6 +2267,9 @@ TCPEndpoint::Dump() const
kprintf(" max segment size: %lu\n", (uint32)fReceiveMaxSegmentSize); kprintf(" max segment size: %lu\n", (uint32)fReceiveMaxSegmentSize);
kprintf(" queue: %lu / %lu\n", fReceiveQueue.Available(), kprintf(" queue: %lu / %lu\n", fReceiveQueue.Available(),
fReceiveQueue.Size()); fReceiveQueue.Size());
#if DEBUG_BUFFER_QUEUE
fReceiveQueue.Dump();
#endif
kprintf(" initial sequence: %lu\n", (uint32)fInitialReceiveSequence); kprintf(" initial sequence: %lu\n", (uint32)fInitialReceiveSequence);
kprintf(" duplicate acknowledge count: %lu\n", kprintf(" duplicate acknowledge count: %lu\n",
fDuplicateAcknowledgeCount); fDuplicateAcknowledgeCount);