for libecap::Host classes and a message translator.
TODO: MessageTranslator should probably be renamed to MessageRep for
consistency and brevity reasons. It also lacks most of the code.
--- /dev/null
+
+/*
+ * $Id$
+ */
+
+#include "squid.h"
+
+#include <libecap/common/registry.h>
+#include "eCAP/Host.h"
+#include "eCAP/ServiceRep.h"
+#include "eCAP/Config.h"
+
+Ecap::Config Ecap::TheConfig;
+
+Ecap::Config::Config()
+{
+}
+
+Ecap::Config::~Config()
+{
+}
+
+void
+Ecap::Config::finalize() {
+ Adaptation::Config::finalize();
+ static Ecap::Host *TheHost = new Ecap::Host;
+ libecap::RegisterHost(TheHost);
+}
+
+Adaptation::ServicePointer
+Ecap::Config::createService(const Adaptation::ServiceConfig &cfg)
+{
+ Adaptation::ServicePointer s = new Ecap::ServiceRep(cfg);
+ return s.getRaw();
+}
+
--- /dev/null
+
+/*
+ * $Id$
+ *
+ */
+
+#ifndef SQUID_ECAP_CONFIG_H
+#define SQUID_ECAP_CONFIG_H
+
+#include "adaptation/Config.h"
+
+namespace Ecap {
+
+class Config: public Adaptation::Config
+{
+
+public:
+ Config();
+ ~Config();
+
+ virtual void finalize();
+
+private:
+ Config(const Config &); // not implemented
+ Config &operator =(const Config &); // not implemented
+
+ virtual Adaptation::ServicePointer createService(const Adaptation::ServiceConfig &cfg);
+};
+
+extern Config TheConfig;
+
+} // namespace Ecap
+
+#endif /* SQUID_ECAP_CONFIG_H */
--- /dev/null
+#include "squid.h"
+#include <libecap/adapter/service.h>
+#include "TextException.h"
+#include "eCAP/ServiceRep.h"
+#include "eCAP/Host.h"
+
+
+std::string
+Ecap::Host::uri() const
+{
+ return "ecap://squid-cache.org/ecap/hosts/squid";
+}
+
+void
+Ecap::Host::describe(std::ostream &os) const
+{
+ os << PACKAGE_NAME << " v" << PACKAGE_VERSION;
+}
+
+void
+Ecap::Host::noteService(const libecap::weak_ptr<libecap::adapter::Service> &weak)
+{
+ // Many ecap_service lines may use the same service URI. Find each
+ // matching service rep, make sure it is an eCAP rep,
+ // and update it with the actual eCAP service.
+ int found = 0;
+
+ libecap::shared_ptr<libecap::adapter::Service> shared(weak);
+ typedef Adaptation::Services::iterator SI;
+ for (SI i = Adaptation::AllServices().begin(); i != Adaptation::AllServices().end(); ++i) {
+ if ((*i)->cfg().uri == shared->uri().c_str()) {
+ ServiceRep *rep = dynamic_cast<ServiceRep*>(i->getRaw());
+ Must(rep);
+ rep->noteService(shared);
+ ++found;
+ }
+ }
+
+ debugs(93,5, "Found " << found << " ecap_service configs for " <<
+ shared->uri());
+ if (!found) {
+ debugs(93,1, "Warning: ignoring loaded eCAP module service without " <<
+ "a matching ecap_service configuration: " << shared->uri());
+ }
+}
+
+static int
+SquidLogLevel(libecap::LogVerbosity lv)
+{
+ if (lv.critical())
+ return DBG_CRITICAL; // is it a good idea to ignore other flags?
+
+ if (lv.large())
+ return DBG_DATA; // is it a good idea to ignore other flags?
+
+ if (lv.application())
+ return DBG_DATA; // is it a good idea to ignore other flags?
+
+ return 2 + 2*lv.debugging() + 3*lv.operation() + 2*lv.xaction();
+}
+
+std::ostream *
+Ecap::Host::openDebug(libecap::LogVerbosity lv)
+{
+ const int squidLevel = SquidLogLevel(lv);
+ const int squidSection = 93; // XXX: this should be a global constant
+ // XXX: Debug.h should provide this to us
+ if ((Debug::level = squidLevel) <= Debug::Levels[squidSection])
+ return &Debug::getDebugOut();
+ else
+ return NULL;
+}
+
+void
+Ecap::Host::closeDebug(std::ostream *debug)
+{
+ if (debug)
+ Debug::finishDebug();
+}
--- /dev/null
+
+/*
+ * $Id$
+ */
+
+#ifndef SQUID_ECAP_HOST_H
+#define SQUID_ECAP_HOST_H
+
+#include <libecap/host/host.h>
+
+namespace Ecap {
+
+// Squid wrapper, providing host application functionality to eCAP services.
+class Host : public libecap::host::Host
+{
+public:
+ // About
+ virtual std::string uri() const; // unique across all vendors
+ virtual void describe(std::ostream &os) const; // free-format info
+
+ // Service management
+ virtual void noteService(const libecap::weak_ptr<libecap::adapter::Service> &s);
+
+ // Logging
+ virtual std::ostream *openDebug(libecap::LogVerbosity lv);
+ virtual void closeDebug(std::ostream *debug);
+};
+
+} // namespace Ecap
+
+#endif /* SQUID_ECAP_HOST_H */
noinst_LTLIBRARIES = libeCAP.la
libeCAP_la_SOURCES = \
+ Config.h \
+ Config.cc \
+ Host.h \
+ Host.cc \
+ MessageTranslator.h \
+ MessageTranslator.cc \
+ ServiceRep.h \
+ ServiceRep.cc \
+ XactionRep.h \
+ XactionRep.cc \
+ \
Registry.h
INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_srcdir)/src
-
-
-# Sample adapter section.
-
-EXTRA_DIST = \
- MinimalAdapter.cc
-
-lib_LTLIBRARIES = MinimalAdapter.la
-MinimalAdapter_la_SOURCES = MinimalAdapter.cc
-MinimalAdapter_la_LDFLAGS = -module -avoid-version
-MinimalAdapter_la_LIBADD = ./libeCAP.la
--- /dev/null
+/*
+ * DEBUG: section XXX
+ */
+
+#include "squid.h"
+#include "adaptation/Message.h"
+#include "eCAP/MessageTranslator.h"
+
--- /dev/null
+
+/*
+ * $Id$
+ */
+
+#ifndef SQUID__ECAP__MESSAGE_TRANSLATOR_H
+#define SQUID__ECAP__MESSAGE_TRANSLATOR_H
+
+#include "adaptation/forward.h"
+#include <libecap/common/message.h>
+
+namespace Ecap {
+
+// Translates Squid Adaptation::Message into libecap::Message.
+class MessageTranslator: public libecap::Message
+{
+
+public:
+ MessageTranslator(Adaptation::Message &aMessage): theMessage(aMessage) {}
+
+private:
+ Adaptation::Message &theMessage; // the message being translated to libecap
+};
+
+} // namespace Ecap;
+
+#endif /* SQUID__E_CAP__MESSAGE_TRANSLATOR_H */
--- /dev/null
+#include "squid.h"
+#include <libecap/adapter/service.h>
+#include "TextException.h"
+#include "assert.h"
+#include "eCAP/ServiceRep.h"
+#include "eCAP/XactionRep.h"
+
+Ecap::ServiceRep::ServiceRep(const Adaptation::ServiceConfig &cfg):
+ /*AsyncJob("Ecap::ServiceRep"),*/ Adaptation::Service(cfg)
+{
+}
+
+Ecap::ServiceRep::~ServiceRep()
+{
+}
+
+void Ecap::ServiceRep::noteService(const AdapterService &s) {
+ Must(s != NULL);
+ theService = s;
+ debugs(93,7, "Matched loaded and configured eCAP services: " <<
+ s->uri() << ' ' << cfg().key << "\n");
+}
+
+void Ecap::ServiceRep::invalidate() {
+ theService->retire();
+ theService.reset();
+}
+
+void Ecap::ServiceRep::noteFailure() {
+ assert(false); // XXX: should this be ICAP-specific?
+}
+
+void
+Ecap::ServiceRep::finalize()
+{
+ Adaptation::Service::finalize();
+ if (!theService) {
+ debugs(93,1, "Warning: configured ecap_service was not loaded: " <<
+ cfg().uri);
+ }
+}
+
+bool Ecap::ServiceRep::probed() const
+{
+ return true; // we "probe" the adapter in finalize().
+}
+
+bool Ecap::ServiceRep::up() const
+{
+ return theService != NULL;
+}
+
+bool Ecap::ServiceRep::wantsUrl(const String &urlPath) const
+{
+ Must(up());
+ return theService->wantsUrl(urlPath.buf());
+}
+
+Adaptation::Initiate *
+Ecap::ServiceRep::makeXactLauncher(Adaptation::Initiator *initiator,
+ HttpMsg *virgin, HttpRequest *cause)
+{
+ Must(up());
+ XactionRep *rep = new XactionRep(initiator, virgin, cause, Pointer(this));
+ XactionRep::AdapterXaction x(theService->makeXaction(rep));
+ rep->master(x);
+ return rep;
+}
+
+// returns a temporary string depicting service status, for debugging
+const char *Ecap::ServiceRep::status() const
+{
+ assert(false); // move generic stuff from ICAP to Adaptation
+ // add theService->status()?
+ return NULL;
+}
--- /dev/null
+
+/*
+ * $Id$
+ */
+
+#ifndef SQUID_ECAP_SERVICE_REP_H
+#define SQUID_ECAP_SERVICE_REP_H
+
+#include "adaptation/Service.h"
+#include "adaptation/forward.h"
+#include <libecap/common/forward.h>
+#include <libecap/common/memory.h>
+
+namespace Ecap {
+
+/* The eCAP service representative maintains information about a single eCAP
+ service that Squid communicates with. One eCAP module may register many
+ eCAP services. */
+
+class ServiceRep : public Adaptation::Service
+{
+public:
+ ServiceRep(const Adaptation::ServiceConfig &config);
+ virtual ~ServiceRep();
+
+ typedef libecap::shared_ptr<libecap::adapter::Service> AdapterService;
+ void noteService(const AdapterService &s);
+
+ virtual void finalize();
+
+ // call when the service is no longer needed or valid
+ virtual void invalidate();
+
+ virtual bool probed() const;
+ virtual bool up() const;
+
+ Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause);
+
+ // the methods below can only be called on an up() service
+ virtual bool wantsUrl(const String &urlPath) const;
+
+ // called by transactions to report service failure
+ virtual void noteFailure();
+
+ virtual const char *status() const;
+
+private:
+ AdapterService theService; // the actual adaptation service we represent
+};
+
+} // namespace Ecap
+
+#endif /* SQUID_ECAP_SERVICE_REP_H */
--- /dev/null
+#include "squid.h"
+#include <libecap/adapter/xaction.h>
+#include "TextException.h"
+#include "assert.h"
+#include "HttpRequest.h"
+#include "HttpReply.h"
+#include "eCAP/XactionRep.h"
+
+// CBDATA_CLASS_INIT(Ecap::XactionRep);
+// TODO: add CBDATA_NAMESPACED_CLASS_INIT(namespace, classname)
+cbdata_type Ecap::XactionRep::CBDATA_XactionRep = CBDATA_UNKNOWN;
+
+
+Ecap::XactionRep::XactionRep(Adaptation::Initiator *anInitiator,
+ HttpMsg *virginHeader, HttpRequest *virginCause,
+ const Adaptation::ServicePointer &aService):
+ AsyncJob("Ecap::XactionRep"),
+ Adaptation::Initiate("Ecap::XactionRep", anInitiator, aService),
+ theVirgin(virginHeader), theCause(virginCause),
+ theVirginTranslator(theVirgin), theCauseTranslator(theCause),
+ theAnswerTranslator(theAnswer)
+{
+}
+
+Ecap::XactionRep::~XactionRep()
+{
+ assert(!theMaster);
+}
+
+void
+Ecap::XactionRep::master(const AdapterXaction &x)
+{
+ Must(!theMaster);
+ Must(x != NULL);
+ theMaster = x;
+}
+
+void
+Ecap::XactionRep::start()
+{
+ Must(theMaster);
+ theMaster->start();
+}
+
+void
+Ecap::XactionRep::swangSong()
+{
+ terminateMaster();
+ Adaptation::Initiate::swanSong();
+}
+
+void
+Ecap::XactionRep::terminateMaster()
+{
+ if (theMaster) {
+ AdapterXaction x = theMaster;
+ theMaster.reset();
+ x->stop();
+ }
+}
+
+libecap::Message &
+Ecap::XactionRep::virginMessage()
+{
+ return theVirginTranslator;
+}
+
+libecap::Message &
+Ecap::XactionRep::virginCause()
+{
+ return theCauseTranslator;
+}
+
+void
+Ecap::XactionRep::useVirgin()
+{
+ theMaster.reset();
+ theVirgin.copyTo(theAnswer);
+ sendAnswer(theAnswer.header);
+}
+
+void
+Ecap::XactionRep::cloneVirgin()
+{
+ theVirgin.copyTo(theAnswer);
+}
+
+void
+Ecap::XactionRep::makeAdaptedRequest()
+{
+ theAnswer.set(new HttpRequest);
+}
+
+void
+Ecap::XactionRep::makeAdaptedResponse()
+{
+ theAnswer.set(new HttpReply);
+}
+
+libecap::Message &
+Ecap::XactionRep::adaptedMessage()
+{
+ return theAnswerTranslator;
+}
+
+void
+Ecap::XactionRep::useAdapted()
+{
+ theMaster.reset();
+ sendAnswer(theAnswer.header);
+}
+
+void
+Ecap::XactionRep::useNone()
+{
+ theMaster.reset();
+ tellQueryAborted(true); // should eCAP support retries?
+}
+
+void
+Ecap::XactionRep::noteMoreBodySpaceAvailable(RefCount<BodyPipe> bp)
+{
+ Must(theMaster);
+ theMaster->noteAdaptedSpaceAvailable();
+}
+
+void
+Ecap::XactionRep::noteBodyConsumerAborted(RefCount<BodyPipe> bp)
+{
+ Must(theMaster);
+ theMaster->noteAdaptedAborted();
+}
+
+void
+Ecap::XactionRep::noteMoreBodyDataAvailable(RefCount<BodyPipe> bp)
+{
+ Must(theMaster);
+ theMaster->noteVirginDataAvailable();
+}
+
+void
+Ecap::XactionRep::noteBodyProductionEnded(RefCount<BodyPipe> bp)
+{
+ Must(theMaster);
+ theMaster->noteVirginDataEnded();
+}
+
+void
+Ecap::XactionRep::noteBodyProducerAborted(RefCount<BodyPipe> bp)
+{
+ Must(theMaster);
+ theMaster->noteVirginAborted();
+}
+
+void
+Ecap::XactionRep::noteInitiatorAborted()
+{
+ mustStop("initiator aborted");
+}
+
+const char *Ecap::XactionRep::status() const
+{
+ return Adaptation::Initiate::status();
+}
--- /dev/null
+
+/*
+ * $Id$
+ */
+
+#ifndef SQUID_ECAP_XACTION_REP_H
+#define SQUID_ECAP_XACTION_REP_H
+
+#include "BodyPipe.h"
+#include "adaptation/Initiate.h"
+#include "adaptation/Service.h"
+#include "adaptation/Message.h"
+#include "eCAP/MessageTranslator.h"
+#include <libecap/common/forward.h>
+#include <libecap/common/memory.h>
+#include <libecap/host/xaction.h>
+#include <libecap/adapter/xaction.h>
+
+namespace Ecap {
+
+/* The eCAP xaction representative maintains information about a single eCAP
+ xaction that Squid communicates with. One eCAP module may register many
+ eCAP xactions. */
+class XactionRep : public Adaptation::Initiate, public libecap::host::Xaction,
+ public BodyProducer, public BodyConsumer
+{
+public:
+ XactionRep(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServicePointer &service);
+ virtual ~XactionRep();
+
+ typedef libecap::shared_ptr<libecap::adapter::Xaction> AdapterXaction;
+ void master(const AdapterXaction &aMaster); // establish a link
+
+ // libecap::host::Xaction API
+ virtual libecap::Message &virginMessage() ; // request or response
+ virtual libecap::Message &virginCause() ; // request for the above response
+ virtual void useVirgin() ; // final answer: no adaptation
+ virtual void cloneVirgin() ; // adapted message starts as virgin
+ virtual void makeAdaptedRequest() ; // make fresh adapted request
+ virtual void makeAdaptedResponse() ; // make fresh adapted response
+ virtual libecap::Message &adaptedMessage() ; // request or response
+ virtual void useAdapted() ; // final answer: adapted msg is ready
+ virtual void useNone() ; // final answer: no answer
+
+ // BodyProducer API
+ virtual void noteMoreBodySpaceAvailable(RefCount<BodyPipe> bp);
+ virtual void noteBodyConsumerAborted(RefCount<BodyPipe> bp);
+
+ // BodyConsumer API
+ virtual void noteMoreBodyDataAvailable(RefCount<BodyPipe> bp);
+ virtual void noteBodyProductionEnded(RefCount<BodyPipe> bp);
+ virtual void noteBodyProducerAborted(RefCount<BodyPipe> bp);
+
+ // Initiate API
+ virtual void noteInitiatorAborted();
+
+ // AsyncJob API (via Initiate)
+ virtual void start();
+ virtual void swangSong();
+ virtual const char *status() const;
+
+protected:
+ void terminateMaster();
+
+private:
+ AdapterXaction theMaster; // the actual adaptation xaction we represent
+
+ Adaptation::Message theVirgin;
+ Adaptation::Message theCause;
+ Adaptation::Message theAnswer;
+ MessageTranslator theVirginTranslator;
+ MessageTranslator theCauseTranslator;
+ MessageTranslator theAnswerTranslator;
+
+ CBDATA_CLASS2(XactionRep);
+};
+
+} // namespace Ecap
+
+#endif /* SQUID_ECAP_XACTION_REP_H */