]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/ecap/ServiceRep.cc
2 * DEBUG: section 93 eCAP Interface
7 #include <libecap/adapter/service.h>
8 #include <libecap/common/options.h>
9 #include <libecap/common/name.h>
10 #include <libecap/common/named_values.h>
11 #include "adaptation/ecap/Config.h"
12 #include "adaptation/ecap/Host.h"
13 #include "adaptation/ecap/ServiceRep.h"
14 #include "adaptation/ecap/XactionRep.h"
15 #include "base/TextException.h"
17 // configured eCAP service wrappers
18 static std::list
<Adaptation::Ecap::ServiceRep::AdapterService
> TheServices
;
25 /// wraps Adaptation::Ecap::ServiceConfig to allow eCAP visitors
26 class ConfigRep
: public libecap::Options
29 typedef Adaptation::Ecap::ServiceConfig Master
;
30 typedef libecap::Name Name
;
31 typedef libecap::Area Area
;
33 ConfigRep(const Master
&aMaster
);
35 // libecap::Options API
36 virtual const libecap::Area
option(const libecap::Name
&name
) const;
37 virtual void visitEachOption(libecap::NamedValueVisitor
&visitor
) const;
39 const Master
&master
; ///< the configuration being wrapped
43 } // namespace Adaptation
45 Adaptation::Ecap::ConfigRep::ConfigRep(const Master
&aMaster
): master(aMaster
)
50 Adaptation::Ecap::ConfigRep::option(const libecap::Name
&name
) const
52 // we may supply the params we know about, but only when names have host ID
53 if (name
== metaBypassable
)
54 return Area(master
.bypass
? "1" : "0", 1);
56 // TODO: We could build a by-name index, but is it worth it? Good adapters
57 // should use visitEachOption() instead, to check for name typos/errors.
58 typedef Master::Extensions::const_iterator MECI
;
59 for (MECI i
= master
.extensions
.begin(); i
!= master
.extensions
.end(); ++i
) {
61 return Area(i
->second
.data(), i
->second
.size());
68 Adaptation::Ecap::ConfigRep::visitEachOption(libecap::NamedValueVisitor
&visitor
) const
70 // we may supply the params we know about too, but only if we set host ID
71 visitor
.visit(metaBypassable
, Area(master
.bypass
? "1" : "0", 1));
73 // visit adapter-specific options (i.e., those not recognized by Squid)
74 typedef Master::Extensions::const_iterator MECI
;
75 for (MECI i
= master
.extensions
.begin(); i
!= master
.extensions
.end(); ++i
)
76 visitor
.visit(Name(i
->first
), Area::FromTempString(i
->second
));
79 Adaptation::Ecap::ServiceRep::ServiceRep(const ServiceConfigPointer
&cfg
):
80 /*AsyncJob("Adaptation::Ecap::ServiceRep"),*/ Adaptation::Service(cfg
),
85 Adaptation::Ecap::ServiceRep::~ServiceRep()
89 void Adaptation::Ecap::ServiceRep::noteFailure()
91 assert(false); // XXX: should this be ICAP-specific?
95 Adaptation::Ecap::ServiceRep::finalize()
97 Adaptation::Service::finalize();
98 theService
= FindAdapterService(cfg().uri
);
101 tryConfigureAndStart();
103 } catch (const std::exception
&e
) { // standardized exceptions
104 if (!handleFinalizeFailure(e
.what()))
105 throw; // rethrow for upper layers to handle
106 } catch (...) { // all other exceptions
107 if (!handleFinalizeFailure("unrecognized exception"))
108 throw; // rethrow for upper layers to handle
110 return; // success or handled exception
112 debugs(93,DBG_IMPORTANT
, "WARNING: configured ecap_service was not loaded: " << cfg().uri
);
116 /// attempts to configure and start eCAP service; the caller handles exceptions
118 Adaptation::Ecap::ServiceRep::tryConfigureAndStart()
120 debugs(93,2, HERE
<< "configuring eCAP service: " << theService
->uri());
121 const ConfigRep
cfgRep(dynamic_cast<const ServiceConfig
&>(cfg()));
122 theService
->configure(cfgRep
);
124 debugs(93,DBG_IMPORTANT
, "Starting eCAP service: " << theService
->uri());
128 /// handles failures while configuring or starting an eCAP service;
129 /// returns false if the error must be propagated to higher levels
131 Adaptation::Ecap::ServiceRep::handleFinalizeFailure(const char *error
)
133 const bool salvage
= cfg().bypass
;
134 const int level
= salvage
? DBG_IMPORTANT
:DBG_CRITICAL
;
135 const char *kind
= salvage
? "optional" : "essential";
136 debugs(93, level
, "ERROR: failed to start " << kind
<< " eCAP service: " <<
137 cfg().uri
<< ":\n" << error
);
140 return false; // we cannot handle the problem; the caller may escalate
142 // make up() false, preventing new adaptation requests and enabling bypass
144 debugs(93, level
, "WARNING: " << kind
<< " eCAP service is " <<
145 "down after initialization failure: " << cfg().uri
);
147 return true; // tell the caller to ignore the problem because we handled it
150 bool Adaptation::Ecap::ServiceRep::probed() const
152 return true; // we "probe" the adapter in finalize().
155 bool Adaptation::Ecap::ServiceRep::up() const
157 return theService
!= NULL
;
160 bool Adaptation::Ecap::ServiceRep::wantsUrl(const String
&urlPath
) const
163 return theService
->wantsUrl(urlPath
.termedBuf());
166 Adaptation::Initiate
*
167 Adaptation::Ecap::ServiceRep::makeXactLauncher(HttpMsg
*virgin
,
171 XactionRep
*rep
= new XactionRep(virgin
, cause
, Pointer(this));
172 XactionRep::AdapterXaction
x(theService
->makeXaction(rep
));
177 // returns a temporary string depicting service status, for debugging
178 const char *Adaptation::Ecap::ServiceRep::status() const
180 // TODO: move generic stuff from eCAP and ICAP to Adaptation
189 buf
.append("down", 4);
192 buf
.append(",detached", 9);
197 return buf
.content();
200 void Adaptation::Ecap::ServiceRep::detach()
205 bool Adaptation::Ecap::ServiceRep::detached() const
210 Adaptation::Ecap::ServiceRep::AdapterService
211 Adaptation::Ecap::FindAdapterService(const String
& serviceUri
)
213 typedef std::list
<ServiceRep::AdapterService
>::const_iterator ASCI
;
214 for (ASCI s
= TheServices
.begin(); s
!= TheServices
.end(); ++s
) {
216 if (serviceUri
== (*s
)->uri().c_str())
219 return ServiceRep::AdapterService();
223 Adaptation::Ecap::RegisterAdapterService(const Adaptation::Ecap::ServiceRep::AdapterService
& adapterService
)
225 typedef std::list
<ServiceRep::AdapterService
>::iterator ASI
;
226 for (ASI s
= TheServices
.begin(); s
!= TheServices
.end(); ++s
) {
228 if (adapterService
->uri() == (*s
)->uri()) {
230 debugs(93, 3, "updated eCAP module service: " <<
231 adapterService
->uri());
235 TheServices
.push_back(adapterService
);
236 debugs(93, 3, "registered eCAP module service: " << adapterService
->uri());
240 Adaptation::Ecap::UnregisterAdapterService(const String
& serviceUri
)
242 typedef std::list
<ServiceRep::AdapterService
>::iterator ASI
;
243 for (ASI s
= TheServices
.begin(); s
!= TheServices
.end(); ++s
) {
244 if (serviceUri
== (*s
)->uri().c_str()) {
245 TheServices
.erase(s
);
246 debugs(93, 3, "unregistered eCAP module service: " << serviceUri
);
250 debugs(93, 3, "failed to unregister eCAP module service: " << serviceUri
);
254 Adaptation::Ecap::CheckUnusedAdapterServices(const Adaptation::Services
& cfgs
)
256 typedef std::list
<ServiceRep::AdapterService
>::const_iterator ASCI
;
257 for (ASCI loaded
= TheServices
.begin(); loaded
!= TheServices
.end();
260 for (Services::const_iterator cfged
= cfgs
.begin();
261 cfged
!= cfgs
.end() && !found
; ++cfged
) {
262 found
= (*cfged
)->cfg().uri
== (*loaded
)->uri().c_str();
265 debugs(93, DBG_IMPORTANT
, "Warning: loaded eCAP service has no matching " <<
266 "ecap_service config option: " << (*loaded
)->uri());