Skip to content

Commit

Permalink
exception handling added to component creation and destruction
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilya Golubtsov committed May 10, 2011
1 parent ad134ad commit 0f795d6
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 50 deletions.
6 changes: 6 additions & 0 deletions debian/changelog
@@ -1,3 +1,9 @@
fastcgi-daemon2 (2.9-2) unstable; urgency=low

* exception handling added to component creation and destruction

-- Ilya Golubtsov (Ilya) <golubtsov@yandex-team.ru> Tue, 10 May 2011 11:06:26 +0400

fastcgi-daemon2 (2.9-1) unstable; urgency=low

* query filter added to handler
Expand Down
2 changes: 1 addition & 1 deletion fastcgi-daemon2-bf.spec
@@ -1,7 +1,7 @@
Summary: fastcgi-daemon2 is an application server for FastCGI
Name: fastcgi-daemon2
Version: 2.9
Release: 1%{?dist}
Release: 2%{?dist}

License: Yandex License
Group: System Environment/Libraries
Expand Down
2 changes: 1 addition & 1 deletion fastcgi-daemon2.spec
Expand Up @@ -7,7 +7,7 @@
Summary: fastcgi-daemon2 is an application server for FastCGI
Name: fastcgi-daemon2
Version: 2.9
Release: 1%{?dist}
Release: 2%{?dist}

License: Yandex License
Group: System Environment/Libraries
Expand Down
118 changes: 72 additions & 46 deletions library/componentset.cpp
@@ -1,5 +1,6 @@
#include "settings.h"


#include <iostream>
#include <vector>
#include <stdexcept>

Expand All @@ -20,91 +21,116 @@ namespace fastcgi
{

ComponentSet::ComponentContainer::ComponentContainer()
: component(NULL), context(NULL), isLoadingStarted(false)
: component(NULL), context(NULL), isLoadingStarted(false)
{}

ComponentSet::ComponentSet() : globals_(NULL) {
}

ComponentSet::~ComponentSet() {
sendOnUnloadToComponents();
sendOnUnloadToComponents();
for (ComponentMap::reverse_iterator i = components_.rbegin(); i != components_.rend(); ++i) {
delete i->second.component;
delete i->second.component;
delete i->second.context;
}
}

void
ComponentSet::init(const Globals *globals) {
globals_ = globals;
std::vector<std::string> v;
std::string key("/fastcgi/components/component");
globals->config()->subKeys(key, v);
for (std::vector<std::string>::iterator i = v.begin(), end = v.end(); i != end; ++i) {
const std::string name = globals->config()->asString(*i + "/@name");
const std::string type = globals->config()->asString(*i + "/@type");
add(name, type, *i);
}
globals_ = globals;
std::vector<std::string> v;
std::string key("/fastcgi/components/component");
globals->config()->subKeys(key, v);
for (std::vector<std::string>::iterator i = v.begin(), end = v.end(); i != end; ++i) {
const std::string name = globals->config()->asString(*i + "/@name");
const std::string type = globals->config()->asString(*i + "/@type");
add(name, type, *i);
}
sendOnLoadToComponents();
}

Component*
ComponentSet::find(const std::string &name) const {
ComponentSet *nonConstThis = const_cast<ComponentSet*>(this);
ComponentMap::iterator i = nonConstThis->components_.find(name);
ComponentSet *nonConstThis = const_cast<ComponentSet*>(this);
ComponentMap::iterator i = nonConstThis->components_.find(name);
if (i != components_.end()) {
ComponentContainer &cont = i->second;
if (!isComponentLoaded(name)) {
nonConstThis->sendOnLoad(name, cont);
}
return cont.component;
}
return NULL;
ComponentContainer &cont = i->second;
if (!isComponentLoaded(name)) {
nonConstThis->sendOnLoad(name, cont);
}
return cont.component;
}
return NULL;
}

void
ComponentSet::add(const std::string &name, const std::string &type,
const std::string &componentXPath) {
ComponentFactory *factory = globals_->loader()->findComponentFactory(type);
const std::string &componentXPath) {
ComponentFactory *factory = globals_->loader()->findComponentFactory(type);
if (!factory) {
throw std::runtime_error("Cannot find component factory for type: " + type);
}
ComponentContainer c;
c.context = new ComponentContextImpl(globals_, componentXPath);
c.component = factory->createComponent(c.context);
components_.insert(make_pair(name, c));
throw std::runtime_error("Cannot find component factory for type: " + type);
}
ComponentContainer c;
std::auto_ptr<ComponentContext> ctx(new ComponentContextImpl(globals_, componentXPath));
try {
c.component = factory->createComponent(ctx.get());
}
catch (const std::exception &e) {
throw std::runtime_error(e.what());
}
catch (...) {
throw std::runtime_error("Unknown exception caught");
}
c.context = ctx.release();
components_.insert(make_pair(name, c));
}

void
ComponentSet::sendOnLoadToComponents() {
for (ComponentMap::iterator i = components_.begin(); i != components_.end(); ++i) {
sendOnLoad(i->first, i->second);
for (ComponentMap::iterator i = components_.begin(); i != components_.end(); ++i) {
sendOnLoad(i->first, i->second);
}
}

void
ComponentSet::sendOnLoad(const std::string &componentName, ComponentContainer &cont) {
if (!isComponentLoaded(componentName)) {
if (cont.isLoadingStarted) {
throw std::runtime_error("Cyclic component dependence found");
}
cont.isLoadingStarted = true;
cont.component->onLoad();
loadingStack_.push_back(componentName);
}
if (!isComponentLoaded(componentName)) {
if (cont.isLoadingStarted) {
throw std::runtime_error("Cyclic component dependence found");
}
cont.isLoadingStarted = true;
try {
cont.component->onLoad();
}
catch (const std::exception &e) {
throw std::runtime_error(e.what());
}
catch (...) {
throw std::runtime_error("Unknown exception caught");
}
loadingStack_.push_back(componentName);
}
}

void
ComponentSet::sendOnUnloadToComponents() {
for (std::vector<std::string>::reverse_iterator i = loadingStack_.rbegin(); i != loadingStack_.rend(); ++i) {
ComponentContainer cont = components_.find(*i)->second;
cont.component->onUnload();
}
for (std::vector<std::string>::reverse_iterator i = loadingStack_.rbegin(); i != loadingStack_.rend(); ++i) {
ComponentContainer cont = components_.find(*i)->second;
try {
cont.component->onUnload();
}
catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
catch (...) {
std::cerr << "Unknown exception caught" << std::endl;
}
}
}

bool
ComponentSet::isComponentLoaded(const std::string &componentName) const {
return std::find(loadingStack_.begin(), loadingStack_.end(), componentName) != loadingStack_.end();
return std::find(loadingStack_.begin(), loadingStack_.end(), componentName) != loadingStack_.end();
}

} // namespace fastcgi
4 changes: 2 additions & 2 deletions main/main.cpp
Expand Up @@ -37,8 +37,8 @@ main(int argc, char *argv[]) {

using namespace fastcgi;
try {
std::auto_ptr<Config> config = Config::create(argc, argv);
boost::shared_ptr<Globals> globals(new Globals(config.get()));
std::auto_ptr<Config> config = Config::create(argc, argv);
boost::shared_ptr<Globals> globals(new Globals(config.get()));
FCGIServer server(globals);
::server = &server;
setUpSignalHandlers();
Expand Down

0 comments on commit 0f795d6

Please sign in to comment.