* BufferQueue::Get(size_t ...) now always returns successfully if it does not
return an empty buffer. This should avoid losing data in case not everything could be appended due to a resource shortage. * Also, it now assures that fNumBytes and fContiguousBytes are always maintained correctly, thanks to Adrian for pointing this out! This should fix bug #2594. * Added extra debug code to BufferQueue::RemoveUntil() so that it checks whether or not fContiguousBytes could be maintained correctly (ie. if this function is called only as thought). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28859 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5fa4ff6a86
commit
0e5a3fc6c6
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -183,12 +183,10 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Removes all data in the queue up to the \a sequence number as specified.
|
||||
/*! Removes all data in the queue up to the \a sequence number as specified.
|
||||
|
||||
NOTE:
|
||||
If there are missing segments in the buffers to be removed,
|
||||
fContiguousBytes is not maintained correctly!
|
||||
NOTE: If there are missing segments in the buffers to be removed,
|
||||
fContiguousBytes is not maintained correctly!
|
||||
*/
|
||||
status_t
|
||||
BufferQueue::RemoveUntil(tcp_sequence sequence)
|
||||
@ -199,14 +197,20 @@ BufferQueue::RemoveUntil(tcp_sequence sequence)
|
||||
return B_OK;
|
||||
|
||||
SegmentList::Iterator iterator = fList.GetIterator();
|
||||
tcp_sequence lastRemoved = fFirstSequence;
|
||||
net_buffer *buffer = NULL;
|
||||
while ((buffer = iterator.Next()) != NULL && buffer->sequence < sequence) {
|
||||
ASSERT(lastRemoved == buffer->sequence);
|
||||
// This assures that the queue has no holes, and fContiguousBytes
|
||||
// is maintained correctly.
|
||||
|
||||
if (sequence >= buffer->sequence + buffer->size) {
|
||||
// remove this buffer completely
|
||||
iterator.Remove();
|
||||
fNumBytes -= buffer->size;
|
||||
|
||||
fContiguousBytes -= buffer->size;
|
||||
lastRemoved = buffer->sequence + buffer->size;
|
||||
gBufferModule->free(buffer);
|
||||
} else {
|
||||
// remove the header as far as needed
|
||||
@ -229,8 +233,7 @@ BufferQueue::RemoveUntil(tcp_sequence sequence)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Clones the requested data in the buffer queue into the provided \a buffer.
|
||||
/*! Clones the requested data in the buffer queue into the provided \a buffer.
|
||||
*/
|
||||
status_t
|
||||
BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
|
||||
@ -260,8 +263,10 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
|
||||
|
||||
if (source == NULL)
|
||||
panic("we should have had that data...");
|
||||
if (source->sequence > sequence)
|
||||
panic("source %p, sequence = %lu (%lu)\n", source, source->sequence, (uint32)sequence);
|
||||
if (source->sequence > sequence) {
|
||||
panic("source %p, sequence = %lu (%lu)\n", source, source->sequence,
|
||||
(uint32)sequence);
|
||||
}
|
||||
|
||||
// clone the data
|
||||
|
||||
@ -269,7 +274,8 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
|
||||
|
||||
while (source != NULL && bytesLeft > 0) {
|
||||
size_t size = min_c(source->size - offset, bytesLeft);
|
||||
status_t status = gBufferModule->append_cloned(buffer, source, offset, size);
|
||||
status_t status = gBufferModule->append_cloned(buffer, source, offset,
|
||||
size);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
@ -282,8 +288,7 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Creates a new buffer containing \a bytes bytes from the start of the
|
||||
/*! Creates a new buffer containing \a bytes bytes from the start of the
|
||||
buffer queue. If \a remove is \c true, the data is removed from the
|
||||
queue, if not, the data is cloned from the queue.
|
||||
*/
|
||||
@ -345,16 +350,21 @@ BufferQueue::Get(size_t bytes, bool remove, net_buffer **_buffer)
|
||||
}
|
||||
}
|
||||
|
||||
if (status == B_OK) {
|
||||
*_buffer = buffer;
|
||||
if (remove) {
|
||||
fNumBytes -= bytes;
|
||||
fContiguousBytes -= bytes;
|
||||
}
|
||||
} else
|
||||
gBufferModule->free(buffer);
|
||||
if (remove && buffer->size) {
|
||||
fNumBytes -= buffer->size;
|
||||
fContiguousBytes -= buffer->size;
|
||||
}
|
||||
|
||||
return status;
|
||||
// We always return what we got, or else we would lose data
|
||||
if (status < B_OK && buffer->size == 0) {
|
||||
// We could not remove any bytes from the buffer, so
|
||||
// let this call fail.
|
||||
gBufferModule->free(buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
*_buffer = buffer;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user