Improve metadata deserialisation to only update object on success

The low level cache deserialisation was leaving bad data in an low
level cache object in the error case. This fixes it so the object
state only gets modified on successful deserialisation of all the
metadata.
This commit is contained in:
Vincent Sanders 2015-01-28 22:36:10 +00:00
parent ecdf37c6ac
commit 9927232a2d
1 changed files with 46 additions and 22 deletions

View File

@ -1309,6 +1309,9 @@ operror:
* Attempt to retrive and deserialise the metadata for an object from
* the backing store.
*
* This must only update object if it is sucessful otherwise difficult
* to debug crashes happen later by using bad leftover object state.
*
* \param object The object to retrieve the metadata for.
* \return NSERROR_OK if the metatdata was retrived and deserialised
* or error code if url is not in persistant storage or in
@ -1325,6 +1328,11 @@ llcache_process_metadata(llcache_object *object)
uint8_t *end;
char *ln;
int lnsize;
size_t source_length;
time_t request_time;
time_t reponse_time;
time_t completion_time;
size_t num_headers;
size_t hloop;
@ -1348,14 +1356,14 @@ llcache_process_metadata(llcache_object *object)
ln = (char *)metadata;
lnsize = strlen(ln);
if (lnsize < 7)
if (lnsize < 7) {
res = NSERROR_INVALID;
goto format_error;
}
res = nsurl_create(ln, &metadataurl);
if (res != NSERROR_OK) {
guit->llcache->release(object->url, BACKING_STORE_META);
return res;
}
if (res != NSERROR_OK)
goto format_error;
if (nsurl_compare(object->url, metadataurl, NSURL_COMPLETE) != true) {
/* backing store returned the wrong object for the
@ -1382,44 +1390,51 @@ llcache_process_metadata(llcache_object *object)
ln += lnsize + 1;
lnsize = strlen(ln);
if ((lnsize < 1) ||
(sscanf(ln, "%zu", &object->source_len) != 1))
if ((lnsize < 1) || (sscanf(ln, "%zu", &source_length) != 1)) {
res = NSERROR_INVALID;
goto format_error;
object->source_alloc = metadatalen;
}
/* metadata line 3 is the time of request */
line = 3;
ln += lnsize + 1;
lnsize = strlen(ln);
if (nsc_snptimet(ln, lnsize, &object->cache.req_time) != NSERROR_OK)
res = nsc_snptimet(ln, lnsize, &request_time);
if (res != NSERROR_OK)
goto format_error;
/* metadata line 4 is the time of response */
line = 4;
ln += lnsize + 1;
lnsize = strlen(ln);
if (nsc_snptimet(ln, lnsize, &object->cache.res_time) != NSERROR_OK)
res = nsc_snptimet(ln, lnsize, &reponse_time);
if (res != NSERROR_OK)
goto format_error;
/* metadata line 5 is the time of request completion */
line = 5;
ln += lnsize + 1;
lnsize = strlen(ln);
if (nsc_snptimet(ln, lnsize, &object->cache.fin_time) != NSERROR_OK)
res = nsc_snptimet(ln, lnsize, &completion_time);
if (res != NSERROR_OK)
goto format_error;
/* metadata line 6 is the number of headers */
line = 6;
ln += lnsize + 1;
lnsize = strlen(ln);
if ((lnsize < 1) ||
(sscanf(ln, "%zu", &num_headers) != 1))
if ((lnsize < 1) || (sscanf(ln, "%zu", &num_headers) != 1)) {
res = NSERROR_INVALID;
goto format_error;
}
/* read headers */
for (hloop = 0 ; hloop < num_headers; hloop++) {
@ -1427,26 +1442,35 @@ llcache_process_metadata(llcache_object *object)
ln += lnsize + 1;
lnsize = strlen(ln);
res = llcache_fetch_process_header(object, (uint8_t *)ln, lnsize);
if (res != NSERROR_OK) {
guit->llcache->release(object->url, BACKING_STORE_META);
return res;
}
res = llcache_fetch_process_header(object,
(uint8_t *)ln,
lnsize);
if (res != NSERROR_OK)
goto format_error;
}
guit->llcache->release(object->url, BACKING_STORE_META);
/* update object on successful parse of metadata */
object->source_len = source_length;
/** \todo really not sure this is right, nothing is allocated here? */
object->source_alloc = metadatalen;
object->cache.req_time = request_time;
object->cache.res_time = reponse_time;
object->cache.fin_time = completion_time;
/* object stored in backing store */
object->store_state = LLCACHE_STATE_DISC;
return NSERROR_OK;
format_error:
LOG(("metadata error on line %d\n", line));
LOG(("metadata error on line %d error code %d\n", line, res));
guit->llcache->release(object->url, BACKING_STORE_META);
return NSERROR_INVALID;
return res;
}
/**