/* Web Polygraph http://www.web-polygraph.org/ * (C) 2003-2006 The Measurement Factory * Licensed under the Apache License, Version 2.0 */ #include "base/polygraph.h" #include "base/ObjId.h" #include "runtime/Connection.h" #include "runtime/HostMap.h" #include "runtime/HttpDate.h" #include "runtime/polyErrors.h" #include "runtime/httpText.h" #include "runtime/globals.h" #include "csm/ContentCfg.h" #include "server/Server.h" #include "cache/Cache.h" #include "cache/DistrPoint.h" #include "proxy/PxySrvXact.h" void PxySrvXact::reset() { CacheReader::reset(); SrvXact::reset(); waitForCache = true; } // also called from noteCacheReady void PxySrvXact::noteWriteReady(int fd) { Assert(theDistrPoint); const Size prodObjSize = theProducedSize - theRepHdrSize; const Size objSize = theDistrPoint->entry()->objSize(); const Size pendSize = theDistrPoint->readySize() <= 0 ? Size(0) : theDistrPoint->readySize() - prodObjSize; if (objSize >= 0) { Assert(prodObjSize < objSize); if (theRepSize.expected().known()) Assert(objSize == theRepSize.expected() - theRepHdrSize); } waitForCache = pendSize <= 0; if (waitForCache) { // writer may not exist yet // XXX: we need to set a timeout if waiting for the writer // Assert(theDistrPoint->writer()); Assert(prodObjSize < objSize || objSize < 0); theConn->theWr.stop(this); } else { Assert(pendSize > 0); theConn->maxIoSize(pendSize); SrvXact::noteWriteReady(fd); } } // returns content length Size PxySrvXact::put200OkHead(ostream &os) { Assert(theDistrPoint); if (theDistrPoint->hasRepHdr()) return put200OkMiss(os); else return put200OkHit(os); } Size PxySrvXact::put200OkMiss(ostream &os) { const RepHdr &rep = theDistrPoint->cachedRepHdr(); os << (theOid.cachable() ? hfCcCachable : hfCcUncachable); HttpDatePrint(os << hfpDate, rep.theDate >= 0 ? rep.theDate : TheClock.time()) << crlf; // indicate persistency (HTTP/1.0 defaults to non-persistent) if (theConn->reusable()) os << hfConnAlivePxy; if (rep.theExpires >= 0) HttpDatePrint(os << hfpExpires, rep.theExpires) << crlf; if (rep.theLMT >= 0) HttpDatePrint(os << hfpLmt, rep.theLMT) << crlf; Assert(rep.theContSize >= 0); os << hfpContLength << (int)rep.theContSize << crlf; if (theContentCfg->theMimeType) // XXX: should copy os << hfpContType << theContentCfg->theMimeType << crlf; if (rep.theTarget) os << hfpXTarget << rep.theTarget << crlf; if (rep.theXactId) os << hfpXXact << rep.theGroupId << ' ' << rep.theXactId << crlf; if (rep.thePhaseSyncPos) os << hfpXPhaseSyncPos << rep.thePhaseSyncPos << crlf; return rep.theContSize; } Size PxySrvXact::put200OkHit(ostream &os) { os << (theOid.cachable() ? hfCcCachable : hfCcUncachable); HttpDatePrint(os << hfpDate) << crlf; // indicate persistency (HTTP/1.0 defaults to non-persistent) if (theConn->reusable()) os << hfConnAlivePxy; if (theTimes.knownExp()) HttpDatePrint(os << hfpExpires, theTimes.exp()) << crlf; if (theTimes.showLmt()) HttpDatePrint(os << hfpLmt, theTimes.lmt()) << crlf; const Size clen = theContentCfg->calcRepSize(theOid); os << hfpContLength << (int)clen << crlf; if (theContentCfg->theMimeType) os << hfpContType << theContentCfg->theMimeType << crlf; os << hfpXXact << TheGroupId << ' ' << theId << crlf; return clen; } // XXX: nobody calls these? void PxySrvXact::noteWriterLeft() { finish(errPrematureEof); } void PxySrvXact::noteCacheReady() { if (waitForCache) SrvXact::noteWriteReady(theConn->fd()); } void PxySrvXact::newState(State aState) { SrvXact::newState(aState); if (theState == stSpaceWaiting) { Assert(!theDistrPoint); theOid.hit(theOwner->cache()->cached(theOid)); theDistrPoint = theOwner->cache()->addReader(theOid, this); if (!theDistrPoint) { // the cache must report an error // XXX: newState(stSpaceWaiting) may not be the last call in chain! finish(-1); return; } } else if (theState == stDone) { if (theDistrPoint) { theDistrPoint->delReader(this); // XXX: check that it resets theDistrPoint! Assert(!theDistrPoint); } } } const ReqHdr *PxySrvXact::origReqHdrs() const { return &theReqHdr; } Error PxySrvXact::setTarget(const NetAddr &target) { Assert(theOwner->hostIdx() < 0); int targetIdx = -1; if (!TheHostMap->find(target, targetIdx)) return errForeignTarget; theOid.target(targetIdx); return 0; }