/* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1