/*
- * $Id: forward.cc,v 1.154 2007/04/06 04:50:06 rousskov Exp $
+ * $Id: forward.cc,v 1.155 2007/04/12 14:07:10 rousskov Exp $
*
* DEBUG: section 17 Request Forwarding
* AUTHOR: Duane Wessels
;
EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT);
+}
+
+// Called once, right after object creation, when it is safe to set self
+void FwdState::start(Pointer aSelf) {
+ // Protect ourselves from being destroyed when the only Server pointing
+ // to us is gone (while we expect to talk to more Servers later).
+ // Once we set self, we are responsible for clearing it when we do not
+ // expect to talk to any servers.
+ self = aSelf; // refcounted
+
+ // We hope that either the store entry aborts or peer is selected.
+ // Otherwise we are going to leak our object.
- self = this; // refcounted
+ storeRegisterAbort(entry, FwdState::abort, this);
+ peerSelect(request, entry, fwdStartCompleteWrapper, this);
- storeRegisterAbort(e, FwdState::abort, this);
+ // TODO: set self _after_ the peer is selected because we do not need
+ // self until we start talking to some Server.
}
void
return;
default:
- FwdState *fwd = new FwdState(client_fd, entry, request);
- fwd->flags.forward_completed = 0;
- peerSelect(request, entry, fwdStartCompleteWrapper, fwd);
+ FwdState::Pointer fwd = new FwdState(client_fd, entry, request);
+ fwd->start(fwd);
return;
}
storeEntryReset(e);
- /*
- * Need to re-establish the self-reference here since we'll
- * be trying to forward the request again. Otherwise the
- * ref count could go to zero before a connection is
- * established.
- */
- self = this; // refcounted
-
startComplete(servers);
} else {
debug(17, 3) ("fwdComplete: not re-forwarding status %d\n",
entry->complete();
if (server_fd < 0)
completed();
+ self = NULL; // refcounted
}
}
break;
}
}
-
- /*
- * remove our self-refcount now that we've handed off the request
- * to a server-side module
- */
- self = NULL;
}
int
public:
typedef RefCount<FwdState> Pointer;
- FwdState(int fd, StoreEntry *, HttpRequest *);
~FwdState();
static void initModule();
static void RegisterWithCacheManager(CacheManager & manager);
static void serversFree(FwdServer **);
private:
+ // hidden for safer management of self; use static fwdStart
+ FwdState(int fd, StoreEntry *, HttpRequest *);
+ void start(Pointer aSelf);
+
static void logReplyStatus(int tries, http_status status);
void completed();