{
RES_WriteObj(sp);
+ if (sp->obj->objhead != NULL && sp->obj->pass) {
+ /* we will no longer need the storage */
+ HSH_Freestore(sp->obj);
+ }
HSH_Deref(sp->obj);
sp->obj = NULL;
sp->step = STP_DONE;
sp->obj->pass = 1;
sp->obj->cacheable = 1;
- HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
- if (sp->obj->objhead != NULL)
+ if (sp->obj->objhead != NULL) {
+ HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
HSH_Unbusy(sp->obj);
+ }
sp->wrk->acct.fetch++;
sp->step = STP_DELIVER;
return (0);
CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
}
+void
+HSH_Freestore(struct object *o)
+{
+ struct storage *st, *stn;
+
+ TAILQ_FOREACH_SAFE(st, &o->store, list, stn) {
+ CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
+ TAILQ_REMOVE(&o->store, st, list);
+ st->stevedore->free(st);
+ }
+}
+
struct object *
HSH_Lookup(struct sess *sp)
{
HSH_Deref(struct object *o)
{
struct objhead *oh;
- struct storage *st, *stn;
unsigned r;
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
oh = o->objhead;
- if (oh == NULL) {
- /* Pass object, not referenced anywhere */
- free(o);
- return;
- }
-
- CHECK_OBJ(oh, OBJHEAD_MAGIC);
+ if (oh != NULL) {
+ CHECK_OBJ(oh, OBJHEAD_MAGIC);
- /* drop ref on object */
- LOCK(&oh->mtx);
+ /* drop ref on object */
+ LOCK(&oh->mtx);
+ }
assert(o->refcnt > 0);
r = --o->refcnt;
- if (!r)
- TAILQ_REMOVE(&oh->objects, o, list);
- UNLOCK(&oh->mtx);
+ if (oh != NULL) {
+ if (!r)
+ TAILQ_REMOVE(&oh->objects, o, list);
+ UNLOCK(&oh->mtx);
+ }
/* If still referenced, done */
if (r != 0)
return;
- if (o->http.s != NULL) {
+ if (o->http.s != NULL)
free(o->http.s);
- }
- TAILQ_FOREACH_SAFE(st, &o->store, list, stn) {
- CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
- TAILQ_REMOVE(&o->store, st, list);
- st->stevedore->free(st);
- }
+ HSH_Freestore(o);
free(o);
VSL_stats->n_object--;
+ if (oh == NULL)
+ return;
/* Drop our ref on the objhead */
if (hash->deref(oh))
return;