Browse Source

Redesign of applications pool

master
Artyom Beilis 8 years ago
parent
commit
0315b22d34
18 changed files with 617 additions and 171 deletions
  1. +4
    -2
      cppcms/application.h
  2. +195
    -7
      cppcms/applications_pool.h
  3. +3
    -1
      cppcms/http_context.h
  4. +22
    -26
      src/application.cpp
  5. +308
    -92
      src/applications_pool.cpp
  6. +60
    -19
      src/http_context.cpp
  7. +1
    -1
      tests/cookie_test.cpp
  8. +1
    -1
      tests/cppcms_service_test.cpp
  9. +9
    -5
      tests/disco_test.cpp
  10. +1
    -1
      tests/form_test.cpp
  11. +1
    -1
      tests/forwarder_test.cpp
  12. +1
    -1
      tests/gzip_test.cpp
  13. +4
    -3
      tests/http_timeouts_test.cpp
  14. +1
    -1
      tests/jsonrpc_test.cpp
  15. +2
    -4
      tests/proto_test.cpp
  16. +1
    -1
      tests/secure_post_test.cpp
  17. +1
    -1
      tests/session_interface_test.cpp
  18. +2
    -4
      tests/status_test.cpp

+ 4
- 2
cppcms/application.h View File

@@ -32,6 +32,7 @@ namespace cppcms {
class url_dispatcher;
class url_mapper;
class applications_pool;
class application_specific_pool;
class application;
class base_content;
class cache_interface;
@@ -391,8 +392,8 @@ namespace cppcms {
void recycle();
void parent(application *parent);

void pool_id(int id);
int pool_id();
booster::weak_ptr<application_specific_pool> get_pool();
void set_pool(booster::weak_ptr<application_specific_pool> pool);


struct _data; // future use
@@ -403,6 +404,7 @@ namespace cppcms {

booster::atomic_counter refs_;
friend class applications_pool;
friend class application_specific_pool;
friend void booster::intrusive_ptr_add_ref(application *p);
friend void booster::intrusive_ptr_release(application *p);
};


+ 195
- 7
cppcms/applications_pool.h View File

@@ -12,16 +12,89 @@
#include <booster/noncopyable.h>
#include <booster/hold_ptr.h>
#include <booster/intrusive_ptr.h>
#include <booster/shared_ptr.h>
#include <booster/weak_ptr.h>
#include <booster/enable_shared_from_this.h>

#include <memory>
#include <string>

namespace cppcms {

class application;
}

namespace booster {
void CPPCMS_API intrusive_ptr_add_ref(cppcms::application *p);
void CPPCMS_API intrusive_ptr_release(cppcms::application *p);
}

namespace cppcms {

class service;
class mount_point;
class application_specific_pool;
class applications_pool;
namespace http {
class context;
}

///
/// Flags for application pool management
///
namespace app {
static const int synchronous = 0x0000; ///< Synchronous application
static const int asynchronous = 0x0001; ///< Asynchronous application that operates in asynchronous mode
// TBD
//static const int content_filter = 0x0002; ///< Asynchronous application that validates incoming content during upload

static const int op_mode_mask = 0x000F; /// mask to select sync vs async flags

static const int thread_specific= 0x0010; ///< Make synchronous application thread specific
/// \cond INTERNAL
static const int legacy = 0x8000; ///< Use legacy handling of application life time when the application is created in the event loop and than dispatched as a job to a thread pool
/// \endcond
}

///
/// \brief an interface for creating user applications
///
class CPPCMS_API application_specific_pool :
public booster::noncopyable,
public booster::enable_shared_from_this<application_specific_pool>
{
public:
application_specific_pool();
virtual ~application_specific_pool();

int flags();
void flags(int f);

protected:
///
/// Returns newly created instance of an application, its ownership
/// is transferred
///
virtual application *new_application(service &srv) = 0;
private:
friend class applications_pool;
friend class http::context;
friend void booster::intrusive_ptr_release(cppcms::application *app);

application *get_new(service &srv);

void size(size_t n);
booster::intrusive_ptr<application> get(service &);
void put(application *app);

struct _data;
class _policy;
class _tls_policy;
class _pool_policy;
class _async_policy;
class _async_legacy_policy;
booster::hold_ptr<_data> d;
};

///
/// \brief Application pool is the central class that holds user created applications
///
@@ -42,7 +115,10 @@ namespace cppcms {
public:

///
/// \brief a base class for user application factories
/// \brief a base class for user application factories - to be deprecated, use
/// application_specific_pool instead
///
/// \deprecated Use application_specific_pool
///
struct factory : public booster::noncopyable {
///
@@ -58,6 +134,8 @@ namespace cppcms {
///
/// This member function is thread safe.
///
/// \deprecated Use mount(booster::shared_ptr<application_specific_pool> gen,int application_options) instead
///
void mount(std::auto_ptr<factory> aps);
///
@@ -66,7 +144,8 @@ namespace cppcms {
///
/// This member function is thread safe.
///

/// \deprecated Use mount(booster::shared_ptr<application_specific_pool> gen,mount_point const &point,int application_options) instead
///
void mount(std::auto_ptr<factory> aps,mount_point const &point);

///
@@ -75,6 +154,8 @@ namespace cppcms {
///
/// This member function is thread safe.
///
/// \deprecated Use mount(booster::shared_ptr<application_specific_pool> gen,int application_options) with application_options=app::asynchronous instead
///
void mount(booster::intrusive_ptr<application> app);
///
/// Mount an asynchronous application \a app by mount_point \a point application matching and
@@ -82,14 +163,45 @@ namespace cppcms {
///
/// This member function is thread safe.
///
/// \deprecated Use mount(booster::shared_ptr<application_specific_pool> gen,mount_point const &point,int application_options) with application_options=app::asynchronous instead
///
void mount(booster::intrusive_ptr<application> app,mount_point const &point);

///
/// Mount a application_specific_pool for an application that processes all requests, path provided to application's main is PATH_INFO
///
/// \a application_options allow to specify mode of operation - synchronous, asynchronous, see namespace
/// cppcms::app
///
/// Note: applications_pool owns gen now and is responsible for destroying it
///
/// This member function is thread safe.
///
void mount(booster::shared_ptr<application_specific_pool> gen,int application_options = 0);

///
/// Mount a application_specific_pool to a specific mount point
///
/// \a application_options allow to specify mode of operation - synchronous, asynchronous, see namespace
/// cppcms::app
///
/// Note: applications_pool owns gen now and is responsible for destroying it
///
/// This member function is thread safe.
///
void mount(booster::shared_ptr<application_specific_pool> gen,mount_point const &point,int application_options = 0);


/// \cond INTERNAL

/// get is not in use any more
booster::intrusive_ptr<application>
get(char const *h,char const *s,char const *path_info,std::string &match);

booster::shared_ptr<application_specific_pool>
get_application_specific_pool(char const *h,char const *s,char const *path_info,std::string &match);

// put is not in use any more
void put(application *app);
applications_pool(service &srv,int pool_size_limit);
~applications_pool();
@@ -97,9 +209,6 @@ namespace cppcms {
/// \endcond

private:
struct basic_app_data;
struct app_data;
struct long_running_app_data;
struct _data;
service *srv_;
booster::hold_ptr<_data> d;
@@ -147,6 +256,8 @@ namespace cppcms {
/// Create application factory for application of type T, such as T has a constructor
/// T::T(cppcms::service &s);
///
/// \deprecated Use applications_genrator
///
template<typename T>
std::auto_ptr<applications_pool::factory> applications_factory()
{
@@ -158,6 +269,8 @@ namespace cppcms {
/// Create application factory for application of type T, such as T has a constructor
/// T::T(cppcms::service &s,P1);
///
/// \deprecated Use applications_genrator
///
template<typename T,typename P1>
std::auto_ptr<applications_pool::factory> applications_factory(P1 p1)
{
@@ -169,6 +282,8 @@ namespace cppcms {
/// Create application factory for application of type T, such as T has a constructor
/// T::T(cppcms::service &s,P1,P2);
///
/// \deprecated Use applications_genrator
///
template<typename T,typename P1,typename P2>
std::auto_ptr<applications_pool::factory> applications_factory(P1 p1,P2 p2)
{
@@ -176,6 +291,79 @@ namespace cppcms {
return f;
}

/// \cond INTERNAL
namespace details {
template<typename T>
struct simple_application_specific_pool0 : public application_specific_pool
{
T *new_application(service &s)
{
return new T(s);
}
};
template<typename T,typename P1>
struct simple_application_specific_pool1 : public application_specific_pool
{
simple_application_specific_pool1(P1 p1) : p1_(p1) {}
P1 p1_;
T *new_application(service &s)
{
return new T(s,p1_);
}
};
template<typename T,typename P1,typename P2>
struct simple_application_specific_pool2 : public application_specific_pool
{
simple_application_specific_pool2(P1 p1,P2 p2) : p1_(p1),p2_(p2) {}
P1 p1_;
P2 p2_;
T *new_application(service &s)
{
return new T(s,p1_,p2_);
}
};
} // details

/// \endcond

///
/// Create application application_specific_pool for application of type T, such as T has a constructor
/// T::T(cppcms::service &s);
///
/// \deprecated Use applications_genrator
///
template<typename T>
booster::shared_ptr<application_specific_pool> create_pool()
{
booster::shared_ptr<application_specific_pool> f(new details::simple_application_specific_pool0<T>);
return f;
}
///
/// Create application application_specific_pool for application of type T, such as T has a constructor
/// T::T(cppcms::service &s,P1);
///
/// \deprecated Use applications_genrator
///
template<typename T,typename P1>
booster::shared_ptr<application_specific_pool> create_pool(P1 p1)
{
booster::shared_ptr<application_specific_pool> f(new details::simple_application_specific_pool1<T,P1>(p1));
return f;
}
///
/// Create application application_specific_pool for application of type T, such as T has a constructor
/// T::T(cppcms::service &s,P1,P2);
///
/// \deprecated Use applications_genrator
///
template<typename T,typename P1,typename P2>
booster::shared_ptr<application_specific_pool> create_pool(P1 p1,P2 p2)
{
booster::shared_ptr<application_specific_pool> f(new details::simple_application_specific_pool2<T,P1,P2>(p1,p2));
return f;
}

} // cppcms



+ 3
- 1
cppcms/http_context.h View File

@@ -21,6 +21,7 @@ namespace cppcms {

class service;
class application;
class application_specific_pool;
class cache_interface;
class session_interface;
namespace json { class value; }
@@ -165,7 +166,8 @@ namespace cppcms {
void async_on_peer_reset(booster::callback<void()> const &h);
private:
void on_request_ready(bool error);
static void dispatch(booster::intrusive_ptr<application> app,std::string url,bool syncronous);
static void dispatch(booster::shared_ptr<application_specific_pool> const &pool,booster::shared_ptr<context> const &self,std::string const &url);
static void dispatch(booster::intrusive_ptr<application> const &app,std::string const &url,bool syncronous);
void try_restart(bool e);
booster::shared_ptr<context> self();



+ 22
- 26
src/application.cpp View File

@@ -31,16 +31,15 @@ namespace cppcms {

struct application::_data {
_data(cppcms::service *s):
service(s),
pool_id(-1)
service(s)
{
}
cppcms::service *service;
booster::shared_ptr<http::context> conn;
int pool_id;
url_dispatcher url;
booster::hold_ptr<url_mapper> url_map;
std::vector<application *> managed_children;
booster::weak_ptr<application_specific_pool> my_pool;
};

application::application(cppcms::service &srv) :
@@ -110,7 +109,10 @@ booster::shared_ptr<http::context> application::release_context()

bool application::is_asynchronous()
{
return pool_id() < 0;
booster::shared_ptr<application_specific_pool> p=d->my_pool.lock();
if(p && (p->flags() & app::op_mode_mask) != 0)
return true;
return false;
}

void application::assign_context(booster::shared_ptr<http::context> conn)
@@ -118,14 +120,14 @@ void application::assign_context(booster::shared_ptr<http::context> conn)
root()->d->conn=conn;
}

void application::pool_id(int id)
void application::set_pool(booster::weak_ptr<application_specific_pool> p)
{
d->pool_id=id;
d->my_pool = p;
}

int application::pool_id()
booster::weak_ptr<application_specific_pool> application::get_pool()
{
return d->pool_id;
return d->my_pool;
}

application *application::parent()
@@ -362,33 +364,27 @@ namespace booster {
// REMEMBER THIS IS CALLED FROM DESTRUCTOR!!!
void intrusive_ptr_release(cppcms::application *app)
{
// it is called in destructors... So be very careful
if(!app)
return;
try {
app = app->root();
long refs=--(app->refs_);
if(refs > 0)
return;
cppcms::service &service=app->service();

try {
app->recycle();
}
catch(...) {
if(app->pool_id() < 0) {
service.applications_pool().put(app);
}
else
delete app;
throw;
app->recycle();
booster::shared_ptr<cppcms::application_specific_pool> p = app->get_pool().lock();
if(p) {
cppcms::application *tmp = app;
app = 0;
p->put(tmp);
}

service.applications_pool().put(app);
// return the application to pool... or delete it if "pooled"
else
delete app;
}
catch(...)
{
// FIXME LOG IT?
if(app)
delete app;
}
}
} // booster

+ 308
- 92
src/applications_pool.cpp View File

@@ -12,146 +12,362 @@
#include <cppcms/mount_point.h>
#include <cppcms/cppcms_error.h>
#include <cppcms/json.h>
#include <set>
#include <list>
#include <vector>
#include <cppcms/config.h>
#include <booster/regex.h>
#include <booster/shared_ptr.h>
#include <booster/thread.h>
#include <booster/log.h>


namespace cppcms {

struct applications_pool::basic_app_data : public booster::noncopyable {
basic_app_data(mount_point const &p) :
mount_point_(p)
{
}
mount_point mount_point_;
};
struct applications_pool::app_data : public applications_pool::basic_app_data {
app_data(mount_point const &p,std::auto_ptr<applications_pool::factory> f) :
basic_app_data(p),
factory(f),
size(0)
{
}
std::auto_ptr<applications_pool::factory> factory;
class application_specific_pool::_policy {
public:
_policy(application_specific_pool *self) : self_(self) {}
virtual ~_policy() {}
virtual booster::intrusive_ptr<application> get(cppcms::service &srv) = 0;
virtual void put(application *app) = 0;
application *get_new(cppcms::service &srv) { return self_->get_new(srv); }
protected:
application_specific_pool *self_;
};

class application_specific_pool::_tls_policy : public application_specific_pool::_policy {
public:
_tls_policy(application_specific_pool *self) : application_specific_pool::_policy(self) {}

virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
{
application *app = tss_.release();
if(!app)
return get_new(srv);
return app;
}
virtual void put(application *app)
{
if(!app)
return;
tss_.reset(app);
}
private:
booster::thread_specific_ptr<application> tss_;
};

class application_specific_pool::_pool_policy : public application_specific_pool::_policy{
public:
_pool_policy(application_specific_pool *self,size_t n) :
_policy(self)
{
apps_.resize(n,0);
size_ = 0;
}
~_pool_policy()
{
for(size_t i=0;i<size_;i++)
delete apps_[i];
}
virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
{
if(size_ == 0)
return get_new(srv);
size_ --;
application *app = apps_[size_];
apps_[size_]=0;
return app;
}
virtual void put(application *app)
{
if(!app)
return;
if(size_ >= apps_.size())
delete app;
apps_[size_++] = app;
}
private:
std::vector<application *> apps_;
size_t size_;
};

class application_specific_pool::_async_policy : public application_specific_pool::_policy{
public:
_async_policy(application_specific_pool *self) : _policy(self) {}
virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
{
if(!app_)
app_ = get_new(srv);
return app_;
}
virtual void put(application *)
{
// SHOULD NEVER BE CALLED as when pool is destroyed and app_ is destroyed weak_ptr would be invalid
}
private:
booster::intrusive_ptr<application> app_;
};

int size;
std::set<application *> pool;
class application_specific_pool::_async_legacy_policy : public application_specific_pool::_policy{
public:
_async_legacy_policy(application_specific_pool *self) :
_policy(self),
app_(0)
{
}
virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
{
if(self_->flags()==-1)
return 0;
if(!app_)
app_ = get_new(srv);
return app_;
}
virtual void put(application *app)
{
if(!app)
return;
delete app;
app_ = 0;
self_->flags(-1);
}
private:
application *app_;
};


struct application_specific_pool::_data {
int flags;
size_t size;
booster::hold_ptr<application_specific_pool::_policy> policy;
booster::recursive_mutex lock;
};

application_specific_pool::~application_specific_pool()
{
}

application_specific_pool::application_specific_pool() : d(new application_specific_pool::_data())
{
d->flags = 0;
d->size = 0;
}

int application_specific_pool::flags()
{
return d->flags;
}

void application_specific_pool::flags(int flags)
{
if(d->flags == -1 || d->policy.get())
return;
d->flags = flags;
if(flags == -1)
return;

~app_data()
if(flags == (app::asynchronous | app::legacy)) {
d->policy.reset(new _async_legacy_policy(this));
return;
}

if(flags == app::legacy) {
d->policy.reset(new _pool_policy(this,d->size));
return;
}

if((flags & app::op_mode_mask) != app::synchronous) {
d->policy.reset(new _async_policy(this));
return;
}
if(flags & app::thread_specific) {
d->policy.reset(new _tls_policy(this));
}
else {
d->policy.reset(new _pool_policy(this,d->size));
}
}

void application_specific_pool::size(size_t n)
{
d->size = n;
}

application *application_specific_pool::get_new(service &srv)
{
application *a = new_application(srv);
if(!a)
return 0;
a->set_pool(shared_from_this());
return a;
}

void application_specific_pool::put(application *a)
{
booster::unique_lock<booster::recursive_mutex> g(d->lock);

if(d->flags == -1) {
delete a;
return;
}
assert(d->policy.get());
d->policy->put(a);
}

booster::intrusive_ptr<application> application_specific_pool::get(cppcms::service &srv)
{
booster::unique_lock<booster::recursive_mutex> g(d->lock);

if(d->flags == -1)
return 0;
assert(d->policy.get());
booster::intrusive_ptr<application> app = d->policy->get(srv);
return app;
}

namespace impl {
class legacy_sync_pool : public application_specific_pool {
public:
legacy_sync_pool(std::auto_ptr<applications_pool::factory> f)
{
std::set<application *>::iterator p;
for(p=pool.begin();p!=pool.end();++p) {
delete *p;
}
fact_ = f;
}

application *new_application(cppcms::service &srv)
{
std::auto_ptr<application> a = (*fact_)(srv);
return a.release();
}
private:
std::auto_ptr<applications_pool::factory> fact_;
};

struct applications_pool::long_running_app_data : public applications_pool::basic_app_data
class legacy_async_pool : public application_specific_pool
{
long_running_app_data(mount_point const &p) : basic_app_data(p)
public:
legacy_async_pool(booster::intrusive_ptr<application> app)
{
my_ = app.get();
}
application *new_application(cppcms::service &)
{
application *a = my_;
my_ = 0;
return a;
}
private:
application *my_;
};
} // impl

struct applications_pool::_data {

struct applications_pool::_data {
std::vector<booster::shared_ptr<app_data> > apps;
typedef std::map<application *,booster::shared_ptr<long_running_app_data> > long_running_aps_type;
long_running_aps_type long_running_aps;
int limit;
booster::recursive_mutex mutex;
struct attachment {
mount_point mp;
booster::shared_ptr<application_specific_pool> pool;
attachment(booster::shared_ptr<application_specific_pool> p,mount_point const &m) : mp(m), pool(p) {}
};
typedef booster::unique_lock<booster::recursive_mutex> lock_it;
std::list<attachment> apps;
std::list<attachment> legacy_async_apps;
int legacy_limit;
int thread_count;
booster::recursive_mutex lock;
};


applications_pool::applications_pool(service &srv,int limit) :
applications_pool::applications_pool(service &srv,int pool_size_limit) :
srv_(&srv),
d(new applications_pool::_data())
{
d->limit=limit;
d->legacy_limit=pool_size_limit;
d->thread_count = srv_->threads_no();
}
applications_pool::~applications_pool()
{
}

void applications_pool::mount(std::auto_ptr<factory> aps)

void applications_pool::mount(std::auto_ptr<factory> aps,mount_point const &mp)
{
lock_it lock(d->mutex);
d->apps.push_back(booster::shared_ptr<app_data>(new app_data(mount_point(),aps)));
booster::shared_ptr<application_specific_pool> p(new impl::legacy_sync_pool(aps));
p->size(d->legacy_limit);
p->flags(app::legacy);

booster::unique_lock<booster::recursive_mutex> lock(d->lock);
d->apps.push_back(_data::attachment(p,mp));
}
void applications_pool::mount(std::auto_ptr<factory> aps,mount_point const &p)
void applications_pool::mount(std::auto_ptr<factory> aps)
{
lock_it lock(d->mutex);
d->apps.push_back(booster::shared_ptr<app_data>(new app_data(p,aps)));
mount(aps,mount_point());
}
void applications_pool::mount(booster::intrusive_ptr<application> app)
{
lock_it lock(d->mutex);
d->long_running_aps[app.get()]=
booster::shared_ptr<long_running_app_data>(new long_running_app_data(mount_point()));
mount(app,mount_point());
}
void applications_pool::mount(booster::intrusive_ptr<application> app,mount_point const &p)
void applications_pool::mount(booster::intrusive_ptr<application> app,mount_point const &mp)
{
lock_it lock(d->mutex);
d->long_running_aps[app.get()]=
booster::shared_ptr<long_running_app_data>(new long_running_app_data(p));
booster::shared_ptr<application_specific_pool> p(new impl::legacy_async_pool(app));
p->flags(app::legacy | app::asynchronous);

booster::unique_lock<booster::recursive_mutex> lock(d->lock);
d->legacy_async_apps.push_back(_data::attachment(p,mp));
}

booster::intrusive_ptr<application> applications_pool::get( char const *host,
char const *script_name,
char const *path_info,
std::string &m)
void applications_pool::mount(booster::shared_ptr<application_specific_pool> gen,mount_point const &point,int flags)
{
lock_it lock(d->mutex);
for(unsigned i=0;i<d->apps.size();i++) {
std::pair<bool,std::string> match = d->apps[i]->mount_point_.match(host,script_name,path_info);
if(match.first==false)
continue;
m=match.second;
if(flags & app::legacy) {
throw cppcms_error("Direct specification of cppcms::app::legacy flag is forbidden");
}
gen->size(d->thread_count);
gen->flags(flags);
booster::unique_lock<booster::recursive_mutex> lock(d->lock);
d->apps.push_back(_data::attachment(gen,point));
}

if(d->apps[i]->pool.empty()) {
booster::intrusive_ptr<application> app=(*d->apps[i]->factory)(*srv_).release();
app->pool_id(i);
return app;
}
void applications_pool::mount(booster::shared_ptr<application_specific_pool> gen,int flags)
{
mount(gen,mount_point(),flags);
}

d->apps[i]->size--;
booster::intrusive_ptr<application> app(*(d->apps[i]->pool.begin()));
d->apps[i]->pool.erase(app.get());
return app;
}
for(_data::long_running_aps_type::iterator p=d->long_running_aps.begin();p!=d->long_running_aps.end();++p){
std::pair<bool,std::string> match = p->second->mount_point_.match(host,script_name,path_info);
if(match.first == false)
booster::shared_ptr<application_specific_pool>
applications_pool::get_application_specific_pool(char const *host,char const *script_name,char const *path_info,std::string &match)
{
booster::unique_lock<booster::recursive_mutex> lock(d->lock);
for(std::list<_data::attachment>::iterator it = d->apps.begin();it!=d->apps.end();++it) {
std::pair<bool,std::string> m = it->mp.match(host,script_name,path_info);
if(!m.first)
continue;
m=match.second;
booster::intrusive_ptr<application> app=p->first;
return app;
match = m.second;
return it->pool;
}
booster::shared_ptr<application_specific_pool> result;
for(std::list<_data::attachment>::iterator itr = d->legacy_async_apps.begin();itr!=d->legacy_async_apps.end();) {
std::list<_data::attachment>::iterator app_it = itr;
++itr;
if(app_it->pool->flags() == -1) {
d->legacy_async_apps.erase(app_it);
}
else if (!result) {
std::pair<bool,std::string> m = app_it->mp.match(host,script_name,path_info);
if(!m.first)
continue;
match = m.second;
result = app_it->pool;
}
}
return 0;
return result;
}

void applications_pool::put(application *app)
booster::intrusive_ptr<application> applications_pool::get( char const *,
char const *,
char const *,
std::string &)
{
lock_it lock(d->mutex);
if(!app) return;
int id=app->pool_id();
if(id < 0) {
d->long_running_aps.erase(app);
delete app;
return;
}
if(unsigned(id) >= d->apps.size() || d->apps[id]->size >= d->limit) {
delete app;
return;
}
d->apps[id]->pool.insert(app);
d->apps[id]->size++;
throw cppcms_error("THIS IS INTERNAL MEMBER FUNCTION METHOD MUST NOT BE USED");
}

void applications_pool::put(application *)
{
BOOSTER_WARNING("cppcms") << "CALL OF INTERNAL METHOD";
}




+ 60
- 19
src/http_context.cpp View File

@@ -89,12 +89,21 @@ void context::run()
}

namespace {
struct dispatcher {
void (*func)(booster::intrusive_ptr<application>,std::string,bool);
struct dispatcher_legacy {
void (*func)(booster::intrusive_ptr<application> const &,std::string const &,bool);
booster::intrusive_ptr<application> app;
std::string url;
void operator()() { func(app,url,true); }
};
struct dispatcher {
void (*func)(booster::shared_ptr<application_specific_pool> const &,booster::shared_ptr<context> const &,std::string const &);
booster::shared_ptr<application_specific_pool> pool;
booster::shared_ptr<context> ctx;
std::string url;
void operator()() {
func(pool,ctx,url);
}
};
}

void context::on_request_ready(bool error)
@@ -106,28 +115,56 @@ void context::on_request_ready(bool error)
char const *script_name = conn_->cgetenv("SCRIPT_NAME");
std::string matched;

booster::intrusive_ptr<application> app = service().applications_pool().get(host,script_name,path_info,matched);
booster::shared_ptr<application_specific_pool> pool =
service().applications_pool().get_application_specific_pool(
host,
script_name,
path_info,
matched
);

if(!app) {
if(!pool) {
response().io_mode(http::response::asynchronous);
response().make_error_response(http::response::not_found);
async_complete_response();
return;
}

app->assign_context(self());
if(app->is_asynchronous()) {
response().io_mode(http::response::asynchronous);
if(pool->flags() == (app::legacy | app::synchronous) || (pool->flags() & app::op_mode_mask)!=app::synchronous) {
// synchronous legacy
booster::intrusive_ptr<application> app = pool->get(service());

if(!app) {
response().io_mode(http::response::asynchronous);
response().make_error_response(http::response::internal_server_error);
async_complete_response();
return;
}

app->assign_context(self());

if(pool->flags() == app::legacy) {
dispatcher_legacy dt;
dt.func = &context::dispatch;
dt.app = app;
dt.url.swap(matched);
app->service().thread_pool().post(dt);
return;
}
// Don't post, as context may be reassigned
response().io_mode(http::response::asynchronous);
dispatch(app,matched,false);
return;
}
else {
dispatcher dt;
dt.func = &context::dispatch;
dt.app = app;
dt.pool = pool;
dt.ctx = self();
dt.url.swap(matched);
app->service().thread_pool().post(dt);
service().thread_pool().post(dt);
return;
}
}

@@ -151,7 +188,19 @@ void context::complete_response()
conn_.reset();
}
// static
void context::dispatch(booster::intrusive_ptr<application> app,std::string url,bool syncronous)
void context::dispatch(booster::shared_ptr<application_specific_pool> const &pool,booster::shared_ptr<context> const &self,std::string const &url)
{
booster::intrusive_ptr<application> app = pool->get(self->service());
if(!app) {
self->response().make_error_response(http::response::internal_server_error);
self->complete_response();
return;
}
app->assign_context(self);
dispatch(app,url,true);
}
// static
void context::dispatch(booster::intrusive_ptr<application> const &app,std::string const &url,bool syncronous)
{
try {
if(syncronous && !app->context().service().cached_settings().session.disable_automatic_load)
@@ -189,14 +238,6 @@ void context::dispatch(booster::intrusive_ptr<application> app,std::string url,b
}
}

namespace {
void wrapper(context::handler const &h,bool r)
{
h(r ? context::operation_aborted : context::operation_completed);
}
}


void context::async_flush_output(context::handler const &h)
{
if(response().io_mode() != http::response::asynchronous && response().io_mode()!=http::response::asynchronous_raw) {


+ 1
- 1
tests/cookie_test.cpp View File

@@ -76,7 +76,7 @@ int main(int argc,char **argv)
try {
basic_test();
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
srv.after_fork(submitter(srv));
srv.run();
}


+ 1
- 1
tests/cppcms_service_test.cpp View File

@@ -28,7 +28,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount(cppcms::applications_factory<unit_test>());
srv.applications_pool().mount(cppcms::create_pool<unit_test>());
srv.run();
}
catch(std::exception const &e) {


+ 9
- 5
tests/disco_test.cpp View File

@@ -165,13 +165,17 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
booster::intrusive_ptr<cppcms::application> async = new async_unit_test(srv);
booster::intrusive_ptr<cppcms::application> nb = new nonblocking_unit_test(srv);
srv.applications_pool().mount(
cppcms::create_pool<async_unit_test>(),
cppcms::mount_point("/async"),
cppcms::app::asynchronous);

srv.applications_pool().mount( async, cppcms::mount_point("/async") );
srv.applications_pool().mount( nb, cppcms::mount_point("/nonblocking") );
srv.applications_pool().mount(
cppcms::create_pool<nonblocking_unit_test>(),
cppcms::mount_point("/nonblocking"),
cppcms::app::asynchronous);

srv.applications_pool().mount( cppcms::applications_factory<unit_test>(), cppcms::mount_point("/sync"));
srv.applications_pool().mount( cppcms::create_pool<unit_test>(), cppcms::mount_point("/sync"));
srv.after_fork(submitter(srv));
srv.run();
}


+ 1
- 1
tests/form_test.cpp View File

@@ -273,7 +273,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
srv.after_fork(submitter(srv));
srv.run();
}


+ 1
- 1
tests/forwarder_test.cpp View File

@@ -116,7 +116,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
if(srv.settings().find("test.exec").type()==cppcms::json::is_string)
srv.after_fork(submitter(srv));


+ 1
- 1
tests/gzip_test.cpp View File

@@ -63,7 +63,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
srv.after_fork(submitter(srv));
srv.run();
}


+ 4
- 3
tests/http_timeouts_test.cpp View File

@@ -141,9 +141,10 @@ int main(int argc,char **argv)
try {
cppcms::service srv(argc,argv);
write_tests = srv.settings().get("test.write",false);
booster::intrusive_ptr<cppcms::application> async = new async_test(srv);
srv.applications_pool().mount( async, cppcms::mount_point("/async") );
srv.applications_pool().mount( cppcms::applications_factory<sync_test>(), cppcms::mount_point("/sync"));
srv.applications_pool().mount( cppcms::create_pool<async_test>(),
cppcms::mount_point("/async"),
cppcms::app::asynchronous);
srv.applications_pool().mount( cppcms::create_pool<sync_test>(), cppcms::mount_point("/sync"));
srv.after_fork(submitter(srv));
cppcms::copy_filter flt(std::cerr); // record the log
srv.run();


+ 1
- 1
tests/jsonrpc_test.cpp View File

@@ -107,7 +107,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<json_service>());
srv.applications_pool().mount( cppcms::create_pool<json_service>());
if(srv.settings().type("test.exec")!=cppcms::json::is_undefined)
srv.after_fork(submitter(srv));
srv.run();


+ 2
- 4
tests/proto_test.cpp View File

@@ -61,10 +61,9 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
booster::intrusive_ptr<cppcms::application> app;
if(srv.settings().get("test.async","sync")=="sync") {
std::cout << "Synchronous testing" << std::endl;
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
}
else {
if(srv.settings().get<std::string>("test.async")=="async") {
@@ -80,8 +79,7 @@ int main(int argc,char **argv)
std::cerr << "Invalid configuration value of test.async" << std::endl;
return 1;
}
app=new unit_test(srv);
srv.applications_pool().mount(app);
srv.applications_pool().mount( cppcms::create_pool<unit_test>(),cppcms::app::asynchronous);
}
srv.after_fork(submitter(srv));
srv.run();


+ 1
- 1
tests/secure_post_test.cpp View File

@@ -62,7 +62,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
srv.after_fork(submitter(srv));
srv.run();
}


+ 1
- 1
tests/session_interface_test.cpp View File

@@ -200,7 +200,7 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
srv.after_fork(submitter(srv));
srv.run();
}


+ 2
- 4
tests/status_test.cpp View File

@@ -108,15 +108,13 @@ int main(int argc,char **argv)
{
try {
cppcms::service srv(argc,argv);
booster::intrusive_ptr<cppcms::application> app;
if(srv.settings().get("test.async","sync")=="sync") {
std::cerr << "Synchonous" << std::endl;
srv.applications_pool().mount( cppcms::applications_factory<unit_test>());
srv.applications_pool().mount( cppcms::create_pool<unit_test>());
}
else {
std::cerr << "Asynchonous" << std::endl;
app=new unit_test(srv);
srv.applications_pool().mount(app);
srv.applications_pool().mount( cppcms::create_pool<unit_test>(),cppcms::app::asynchronous);
}
srv.after_fork(submitter(srv));
srv.run();


Loading…
Cancel
Save