http: range transfering ownership of file container

To make concurrency reasoning clearer
pull/6409/head
Philippe Antoine 4 years ago
parent 3ed38d2d5d
commit d776d72711

@ -132,7 +132,7 @@ static inline bool ContainerValueRangeTimeout(HttpRangeContainerFile *cu, struct
// we only timeout if we have no flow referencing us // we only timeout if we have no flow referencing us
if ((uint32_t)ts->tv_sec > cu->expire || cu->error) { if ((uint32_t)ts->tv_sec > cu->expire || cu->error) {
if (SC_ATOMIC_GET(cu->hdata->use_cnt) == 0) { if (SC_ATOMIC_GET(cu->hdata->use_cnt) == 0) {
DEBUG_VALIDATE_BUG_ON(cu->fileOwned); DEBUG_VALIDATE_BUG_ON(cu->files == NULL);
return true; return true;
} }
} }
@ -259,10 +259,7 @@ static HttpRangeContainerBlock *HttpRangeOpenFileAux(HttpRangeContainerFile *c,
uint64_t end, uint64_t total, const StreamingBufferConfig *sbcfg, const uint8_t *name, uint64_t end, uint64_t total, const StreamingBufferConfig *sbcfg, const uint8_t *name,
uint16_t name_len, uint16_t flags) uint16_t name_len, uint16_t flags)
{ {
DEBUG_VALIDATE_BUG_ON(c->files == NULL); if (c->files != NULL && c->files->tail == NULL) {
if (c->files->tail == NULL) {
DEBUG_VALIDATE_BUG_ON(c->fileOwned);
/* this is the first request, we open a single file in the file container /* this is the first request, we open a single file in the file container
* this could be part of ContainerUrlRangeSet if we could have * this could be part of ContainerUrlRangeSet if we could have
* all the arguments there * all the arguments there
@ -277,7 +274,7 @@ static HttpRangeContainerBlock *HttpRangeOpenFileAux(HttpRangeContainerFile *c,
c->error = true; c->error = true;
return NULL; return NULL;
} }
curf->fileOwning = false; curf->files = NULL;
if (total > c->totalsize) { if (total > c->totalsize) {
// we grow to the maximum size indicated by different range requests // we grow to the maximum size indicated by different range requests
// we could add some warning/app-layer event in this case where // we could add some warning/app-layer event in this case where
@ -292,25 +289,25 @@ static HttpRangeContainerBlock *HttpRangeOpenFileAux(HttpRangeContainerFile *c,
* - storing out of order data for later use * - storing out of order data for later use
* - directly appending to the file if we are at the right offset * - directly appending to the file if we are at the right offset
*/ */
if (start == c->lastsize && !c->fileOwned) { if (start == c->lastsize && c->files != NULL) {
// easy case : append to current file // easy case : append to current file
curf->container = c; curf->container = c;
curf->fileOwning = true;
// If we see 2 duplicate range requests with the same range, // If we see 2 duplicate range requests with the same range,
// the first one takes the ownership with fileOwned // the first one takes the ownership of the files container
// protected by the lock from caller HTPFileOpenWithRange // protected by the lock from caller HTPFileOpenWithRange
c->fileOwned = true; curf->files = c->files;
c->files = NULL;
return curf; return curf;
} else if (start < c->lastsize && c->lastsize - start >= buflen) { } else if (start < c->lastsize && c->lastsize - start >= buflen) {
// only overlap // only overlap
// redundant to be explicit that this block is independent // redundant to be explicit that this block is independent
curf->toskip = buflen; curf->toskip = buflen;
return curf; return curf;
} else if (start < c->lastsize && c->lastsize - start < buflen && !c->fileOwned) { } else if (start < c->lastsize && c->lastsize - start < buflen && c->files != NULL) {
// some overlap, then some data to append to the file // some overlap, then some data to append to the file
curf->toskip = c->lastsize - start; curf->toskip = c->lastsize - start;
curf->fileOwning = true; curf->files = c->files;
c->fileOwned = true; c->files = NULL;
curf->container = c; curf->container = c;
return curf; return curf;
} }
@ -373,23 +370,21 @@ int HttpRangeAppendData(HttpRangeContainerBlock *c, const uint8_t *data, uint32_
// then if we need to skip only some bytes // then if we need to skip only some bytes
if (c->toskip > 0) { if (c->toskip > 0) {
int r = 0; int r = 0;
if (c->fileOwning) { if (c->files) {
DEBUG_VALIDATE_BUG_ON(c->container->files == NULL);
if (data == NULL) { if (data == NULL) {
// gap overlaping already known data // gap overlaping already known data
r = FileAppendData(c->container->files, NULL, len - c->toskip); r = FileAppendData(c->files, NULL, len - c->toskip);
} else { } else {
r = FileAppendData(c->container->files, data + c->toskip, len - c->toskip); r = FileAppendData(c->files, data + c->toskip, len - c->toskip);
} }
} }
c->toskip = 0; c->toskip = 0;
return r; return r;
} }
// If we are owning the file to append to it, let's do it // If we are owning the file to append to it, let's do it
if (c->fileOwning) { if (c->files) {
DEBUG_VALIDATE_BUG_ON(c->container->files == NULL);
SCLogDebug("update files (FileAppendData)"); SCLogDebug("update files (FileAppendData)");
return FileAppendData(c->container->files, data, len); return FileAppendData(c->files, data, len);
} }
// If we are not in the previous cases, only one case remains // If we are not in the previous cases, only one case remains
DEBUG_VALIDATE_BUG_ON(c->current == NULL); DEBUG_VALIDATE_BUG_ON(c->current == NULL);
@ -442,8 +437,7 @@ File *HttpRangeClose(HttpRangeContainerBlock *c, uint16_t flags)
if (c->current) { if (c->current) {
SCLogDebug("processing ooo chunk as c->current is set %p", c->current); SCLogDebug("processing ooo chunk as c->current is set %p", c->current);
// some out-or-order range is finished // some out-or-order range is finished
if (c->container->files->tail && if (c->container->lastsize >= c->current->start + c->current->offset) {
c->container->lastsize >= c->current->start + c->current->offset) {
// if the range has become obsolete because we received the data already // if the range has become obsolete because we received the data already
// we just free it // we just free it
(void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, c->current->buflen); (void)SC_ATOMIC_SUB(ContainerUrlRangeList.ht->memuse, c->current->buflen);
@ -476,8 +470,10 @@ File *HttpRangeClose(HttpRangeContainerBlock *c, uint16_t flags)
} }
// we just finished an in-order block // we just finished an in-order block
DEBUG_VALIDATE_BUG_ON(c->container->fileOwned == false); DEBUG_VALIDATE_BUG_ON(c->files == NULL);
c->container->fileOwned = false; // move back the ownership of the file container to HttpRangeContainerFile
c->container->files = c->files;
c->files = NULL;
DEBUG_VALIDATE_BUG_ON(c->container->files->tail == NULL); DEBUG_VALIDATE_BUG_ON(c->container->files->tail == NULL);
// we update the file size now that we own it again // we update the file size now that we own it again
File *f = c->container->files->tail; File *f = c->container->files->tail;
@ -570,6 +566,12 @@ void HttpRangeFreeBlock(HttpRangeContainerBlock *b)
SCFree(b->current->buffer); SCFree(b->current->buffer);
SCFree(b->current); SCFree(b->current);
} }
// we did not move ownership of the file container back to HttpRangeContainerFile
DEBUG_VALIDATE_BUG_ON(b->files != NULL);
if (b->files != NULL) {
FileContainerFree(b->files);
b->files = NULL;
}
SCFree(b); SCFree(b);
} }
} }

@ -75,9 +75,6 @@ typedef struct HttpRangeContainerFile {
struct HTTP_RANGES fragment_tree; struct HTTP_RANGES fragment_tree;
/** file flags */ /** file flags */
uint16_t flags; uint16_t flags;
/** wether a HttpRangeContainerBlock is currently
owning the FileContainer in order to append to the file */
bool fileOwned;
/** error condition for this range. Its up to timeout handling to cleanup */ /** error condition for this range. Its up to timeout handling to cleanup */
bool error; bool error;
} HttpRangeContainerFile; } HttpRangeContainerFile;
@ -94,8 +91,8 @@ typedef struct HttpRangeContainerBlock {
HttpRangeContainerBuffer *current; HttpRangeContainerBuffer *current;
/** pointer to the main file container, where to directly append data */ /** pointer to the main file container, where to directly append data */
HttpRangeContainerFile *container; HttpRangeContainerFile *container;
/** we own the container's file for now */ /** file container we are owning for now */
bool fileOwning; FileContainer *files;
} HttpRangeContainerBlock; } HttpRangeContainerBlock;
int HttpRangeAppendData(HttpRangeContainerBlock *c, const uint8_t *data, uint32_t len); int HttpRangeAppendData(HttpRangeContainerBlock *c, const uint8_t *data, uint32_t len);

Loading…
Cancel
Save