*/
static StreamingBufferRegion *FindFirstRegionForOffset(const StreamingBuffer *sb,
const StreamingBufferConfig *cfg, StreamingBufferRegion *r, const uint64_t offset,
- const uint32_t len)
+ const uint32_t len, StreamingBufferRegion **prev)
{
const uint64_t data_re = offset + len;
SCLogDebug("looking for first region matching %" PRIu64 "/%" PRIu64, offset, data_re);
+ StreamingBufferRegion *p = NULL;
for (; r != NULL; r = r->next) {
- if (RegionsIntersect(sb, cfg, r, offset, data_re) == true)
+ if (RegionsIntersect(sb, cfg, r, offset, data_re) == true) {
+ *prev = p;
return r;
+ }
+ p = r;
}
+ *prev = NULL;
return NULL;
}
static StreamingBufferRegion *BufferInsertAtRegionConsolidate(StreamingBuffer *sb,
const StreamingBufferConfig *cfg, StreamingBufferRegion *dst,
StreamingBufferRegion *src_start, StreamingBufferRegion *src_end,
- const uint64_t data_offset, const uint32_t data_len)
+ const uint64_t data_offset, const uint32_t data_len, StreamingBufferRegion *prev,
+ uint32_t dst_buf_size)
{
+#ifdef DEBUG
const uint64_t data_re = data_offset + data_len;
SCLogDebug("sb %p dst %p src_start %p src_end %p data_offset %" PRIu64
"/data_len %u/data_re %" PRIu64,
sb, dst, src_start, src_end, data_offset, data_len, data_re);
+#endif
- // 1. determine size for dst.
+ // 1. determine size and offset for dst.
const uint64_t dst_offset = MIN(src_start->stream_offset, data_offset);
DEBUG_VALIDATE_BUG_ON(dst_offset < sb->region.stream_offset);
- const uint64_t dst_re = MAX((src_end->stream_offset + src_end->buf_size), data_re);
- const uint32_t dst_size = dst_re - dst_offset;
- SCLogDebug("dst_offset %" PRIu64 ", dst_re %" PRIu64 ", dst_size %u", dst_offset, dst_re,
- dst_size);
+ const uint32_t dst_size = dst_buf_size;
+ SCLogDebug("dst_size %u", dst_size);
// 2. resize dst
const uint32_t old_size = dst->buf_size;
#endif
if (GrowRegionToSize(sb, cfg, dst, dst_size) != 0)
return NULL;
- SCLogDebug("resized to %u", dst_size);
+ SCLogDebug("resized to %u -> %u", dst_size, dst->buf_size);
+ /* validate that the size is exactly what we asked for */
+ DEBUG_VALIDATE_BUG_ON(dst_size != dst->buf_size);
if (dst_copy_offset != 0)
memmove(dst->buf + dst_copy_offset, dst->buf, old_size);
dst->stream_offset = dst_offset;
}
bool start_is_main = false;
- StreamingBufferRegion *prev = NULL;
if (src_start == &sb->region) {
DEBUG_VALIDATE_BUG_ON(src_start->stream_offset != dst_offset);
}
const uint32_t target_offset = r->stream_offset - dst_offset;
SCLogDebug("r %p: target_offset %u", r, target_offset);
+ BUG_ON(target_offset > dst->buf_size);
+ BUG_ON(target_offset + r->buf_size > dst->buf_size);
memcpy(dst->buf + target_offset, r->buf, r->buf_size);
StreamingBufferRegion *next = r->next;
FREE(cfg, r, sizeof(*r));
sb->regions--;
BUG_ON(sb->regions == 0);
+
+ DEBUG_VALIDATE_BUG_ON(prev == NULL && src_start != &sb->region);
if (prev != NULL) {
SCLogDebug("setting prev %p next to %p (was %p)", prev, next, prev->next);
prev->next = next;
const StreamingBufferConfig *cfg, const uint64_t offset, const uint32_t len)
{
SCLogDebug("offset %" PRIu64 ", len %u", offset, len);
- StreamingBufferRegion *start = FindFirstRegionForOffset(sb, cfg, &sb->region, offset, len);
+ StreamingBufferRegion *start_prev = NULL;
+ StreamingBufferRegion *start =
+ FindFirstRegionForOffset(sb, cfg, &sb->region, offset, len, &start_prev);
if (start) {
+ const uint64_t insert_re = offset + len;
+ const uint64_t insert_start_offset = MIN(start->stream_offset, offset);
+ uint64_t insert_adjusted_re = insert_re;
+
SCLogDebug("start region %p/%" PRIu64 "/%u", start, start->stream_offset, start->buf_size);
StreamingBufferRegion *big = FindLargestRegionForOffset(sb, cfg, start, offset, len);
DEBUG_VALIDATE_BUG_ON(big == NULL);
if (big == NULL)
return NULL;
+
SCLogDebug("big region %p/%" PRIu64 "/%u", big, big->stream_offset, big->buf_size);
StreamingBufferRegion *end = FindRightEdge(sb, cfg, big, offset, len);
DEBUG_VALIDATE_BUG_ON(end == NULL);
if (end == NULL)
return NULL;
+ insert_adjusted_re = MAX(insert_adjusted_re, (end->stream_offset + end->buf_size));
+
+ uint32_t new_buf_size =
+ ToNextMultipleOf(insert_adjusted_re - insert_start_offset, cfg->buf_size);
+ SCLogDebug("new_buf_size %u", new_buf_size);
+
+ /* see if our new buf size + cfg->buf_size margin leads to an overlap with the next region.
+ * If so, include that in the consolidation. */
+ if (end->next != NULL && new_buf_size + insert_start_offset > end->next->stream_offset) {
+ SCLogDebug("adjusted end from %p to %p", end, end->next);
+ end = end->next;
+ insert_adjusted_re = MAX(insert_adjusted_re, (end->stream_offset + end->buf_size));
+ new_buf_size =
+ ToNextMultipleOf(insert_adjusted_re - insert_start_offset, cfg->buf_size);
+ SCLogDebug("new_buf_size %u", new_buf_size);
+ }
+
SCLogDebug("end region %p/%" PRIu64 "/%u", end, end->stream_offset, end->buf_size);
- StreamingBufferRegion *ret =
- BufferInsertAtRegionConsolidate(sb, cfg, big, start, end, offset, len);
+ StreamingBufferRegion *ret = BufferInsertAtRegionConsolidate(
+ sb, cfg, big, start, end, offset, len, start_prev, new_buf_size);
return ret;
} else {
/* if there was no region we can use we add a new region and insert it */