ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

405 lines
9.7 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #define CPPCMS_SOURCE
  9. #include <cppcms/applications_pool.h>
  10. #include <cppcms/application.h>
  11. #include <cppcms/service.h>
  12. #include <cppcms/mount_point.h>
  13. #include <cppcms/cppcms_error.h>
  14. #include <cppcms/json.h>
  15. #include <list>
  16. #include <vector>
  17. #include <cppcms/config.h>
  18. #include <booster/regex.h>
  19. #include <booster/shared_ptr.h>
  20. #include <booster/thread.h>
  21. #include <booster/log.h>
  22. namespace cppcms {
  23. class application_specific_pool::_policy {
  24. public:
  25. _policy(application_specific_pool *self) : self_(self) {}
  26. virtual void prepopulate(cppcms::service &srv) = 0;
  27. virtual ~_policy() {}
  28. virtual booster::intrusive_ptr<application> get(cppcms::service &srv) = 0;
  29. virtual void put(application *app) = 0;
  30. application *get_new(cppcms::service &srv) { return self_->get_new(srv); }
  31. protected:
  32. application_specific_pool *self_;
  33. };
  34. class application_specific_pool::_tls_policy : public application_specific_pool::_policy {
  35. public:
  36. _tls_policy(application_specific_pool *self) : application_specific_pool::_policy(self) {}
  37. virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
  38. {
  39. application *app = tss_.release();
  40. if(!app)
  41. return get_new(srv);
  42. return app;
  43. }
  44. virtual void put(application *app)
  45. {
  46. if(!app)
  47. return;
  48. tss_.reset(app);
  49. }
  50. virtual void prepopulate(cppcms::service &){}
  51. private:
  52. booster::thread_specific_ptr<application> tss_;
  53. };
  54. class application_specific_pool::_pool_policy : public application_specific_pool::_policy{
  55. public:
  56. _pool_policy(application_specific_pool *self,size_t n) :
  57. _policy(self)
  58. {
  59. apps_.resize(n,0);
  60. size_ = 0;
  61. }
  62. ~_pool_policy()
  63. {
  64. for(size_t i=0;i<size_;i++)
  65. delete apps_[i];
  66. }
  67. virtual void prepopulate(cppcms::service &srv)
  68. {
  69. if((self_->flags() & app::prepopulated) && !(self_->flags() & app::legacy)) {
  70. while(size_ < apps_.size()) {
  71. size_++;
  72. apps_[size_-1]= get_new(srv);
  73. }
  74. }
  75. }
  76. virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
  77. {
  78. if(size_ == 0)
  79. return get_new(srv);
  80. size_ --;
  81. application *app = apps_[size_];
  82. apps_[size_]=0;
  83. return app;
  84. }
  85. virtual void put(application *app)
  86. {
  87. if(!app)
  88. return;
  89. if(size_ >= apps_.size())
  90. delete app;
  91. apps_[size_++] = app;
  92. }
  93. private:
  94. std::vector<application *> apps_;
  95. size_t size_;
  96. };
  97. class application_specific_pool::_async_policy : public application_specific_pool::_policy{
  98. public:
  99. _async_policy(application_specific_pool *self) :
  100. _policy(self)
  101. {
  102. }
  103. virtual void prepopulate(cppcms::service &srv)
  104. {
  105. if((self_->flags() & app::prepopulated) && !(self_->flags() & app::legacy)) {
  106. if(!app_)
  107. app_ = get_new(srv);
  108. }
  109. }
  110. virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
  111. {
  112. if(!app_)
  113. app_ = get_new(srv);
  114. return app_;
  115. }
  116. virtual void put(application *)
  117. {
  118. // SHOULD NEVER BE CALLED as when pool is destroyed and app_ is destroyed weak_ptr would be invalid
  119. }
  120. private:
  121. booster::intrusive_ptr<application> app_;
  122. };
  123. class application_specific_pool::_async_legacy_policy : public application_specific_pool::_policy{
  124. public:
  125. _async_legacy_policy(application_specific_pool *self) :
  126. _policy(self),
  127. app_(0)
  128. {
  129. }
  130. virtual void prepopulate(cppcms::service &) {}
  131. virtual booster::intrusive_ptr<application> get(cppcms::service &srv)
  132. {
  133. if(self_->flags()==-1)
  134. return 0;
  135. if(!app_)
  136. app_ = get_new(srv);
  137. return app_;
  138. }
  139. virtual void put(application *app)
  140. {
  141. if(!app)
  142. return;
  143. delete app;
  144. app_ = 0;
  145. self_->flags(-1);
  146. }
  147. private:
  148. application *app_;
  149. };
  150. struct application_specific_pool::_data {
  151. int flags;
  152. size_t size;
  153. booster::hold_ptr<application_specific_pool::_policy> policy;
  154. booster::recursive_mutex lock;
  155. };
  156. application_specific_pool::~application_specific_pool()
  157. {
  158. }
  159. application_specific_pool::application_specific_pool() : d(new application_specific_pool::_data())
  160. {
  161. d->flags = 0;
  162. d->size = 0;
  163. }
  164. int application_specific_pool::flags()
  165. {
  166. return d->flags;
  167. }
  168. void application_specific_pool::flags(int flags)
  169. {
  170. if(d->flags == -1 || d->policy.get())
  171. return;
  172. d->flags = flags;
  173. if(flags == -1)
  174. return;
  175. if(flags == (app::asynchronous | app::legacy)) {
  176. d->policy.reset(new _async_legacy_policy(this));
  177. return;
  178. }
  179. if(flags == app::legacy) {
  180. d->policy.reset(new _pool_policy(this,d->size));
  181. return;
  182. }
  183. if((flags & app::op_mode_mask) != app::synchronous) {
  184. d->policy.reset(new _async_policy(this));
  185. return;
  186. }
  187. if(flags & app::thread_specific) {
  188. d->policy.reset(new _tls_policy(this));
  189. }
  190. else {
  191. d->policy.reset(new _pool_policy(this,d->size));
  192. }
  193. }
  194. void application_specific_pool::size(size_t n)
  195. {
  196. d->size = n;
  197. }
  198. application *application_specific_pool::get_new(service &srv)
  199. {
  200. application *a = new_application(srv);
  201. if(!a)
  202. return 0;
  203. a->set_pool(shared_from_this());
  204. return a;
  205. }
  206. void application_specific_pool::put(application *a)
  207. {
  208. booster::unique_lock<booster::recursive_mutex> g(d->lock);
  209. if(d->flags == -1) {
  210. delete a;
  211. return;
  212. }
  213. assert(d->policy.get());
  214. d->policy->put(a);
  215. }
  216. booster::intrusive_ptr<application> application_specific_pool::get(cppcms::service &srv)
  217. {
  218. booster::unique_lock<booster::recursive_mutex> g(d->lock);
  219. if(d->flags == -1)
  220. return 0;
  221. assert(d->policy.get());
  222. booster::intrusive_ptr<application> app = d->policy->get(srv);
  223. return app;
  224. }
  225. void application_specific_pool::prepopulate(cppcms::service &srv)
  226. {
  227. d->policy->prepopulate(srv);
  228. }
  229. namespace impl {
  230. class legacy_sync_pool : public application_specific_pool {
  231. public:
  232. legacy_sync_pool(std::auto_ptr<applications_pool::factory> f)
  233. {
  234. fact_ = f;
  235. }
  236. application *new_application(cppcms::service &srv)
  237. {
  238. std::auto_ptr<application> a = (*fact_)(srv);
  239. return a.release();
  240. }
  241. private:
  242. std::auto_ptr<applications_pool::factory> fact_;
  243. };
  244. class legacy_async_pool : public application_specific_pool
  245. {
  246. public:
  247. legacy_async_pool(booster::intrusive_ptr<application> app)
  248. {
  249. my_ = app.get();
  250. }
  251. application *new_application(cppcms::service &)
  252. {
  253. application *a = my_;
  254. my_ = 0;
  255. return a;
  256. }
  257. private:
  258. application *my_;
  259. };
  260. } // impl
  261. struct applications_pool::_data {
  262. struct attachment {
  263. mount_point mp;
  264. booster::shared_ptr<application_specific_pool> pool;
  265. attachment(booster::shared_ptr<application_specific_pool> p,mount_point const &m) : mp(m), pool(p) {}
  266. };
  267. std::list<attachment> apps;
  268. std::list<attachment> legacy_async_apps;
  269. int legacy_limit;
  270. int thread_count;
  271. booster::recursive_mutex lock;
  272. };
  273. applications_pool::applications_pool(service &srv,int pool_size_limit) :
  274. srv_(&srv),
  275. d(new applications_pool::_data())
  276. {
  277. d->legacy_limit=pool_size_limit;
  278. d->thread_count = srv_->threads_no();
  279. }
  280. applications_pool::~applications_pool()
  281. {
  282. }
  283. void applications_pool::mount(std::auto_ptr<factory> aps,mount_point const &mp)
  284. {
  285. booster::shared_ptr<application_specific_pool> p(new impl::legacy_sync_pool(aps));
  286. p->size(d->legacy_limit);
  287. p->flags(app::legacy);
  288. booster::unique_lock<booster::recursive_mutex> lock(d->lock);
  289. d->apps.push_back(_data::attachment(p,mp));
  290. }
  291. void applications_pool::mount(std::auto_ptr<factory> aps)
  292. {
  293. mount(aps,mount_point());
  294. }
  295. void applications_pool::mount(booster::intrusive_ptr<application> app)
  296. {
  297. mount(app,mount_point());
  298. }
  299. void applications_pool::mount(booster::intrusive_ptr<application> app,mount_point const &mp)
  300. {
  301. booster::shared_ptr<application_specific_pool> p(new impl::legacy_async_pool(app));
  302. p->flags(app::legacy | app::asynchronous);
  303. booster::unique_lock<booster::recursive_mutex> lock(d->lock);
  304. d->legacy_async_apps.push_back(_data::attachment(p,mp));
  305. }
  306. void applications_pool::mount(booster::shared_ptr<application_specific_pool> gen,mount_point const &point,int flags)
  307. {
  308. if(flags & app::legacy) {
  309. throw cppcms_error("Direct specification of cppcms::app::legacy flag is forbidden");
  310. }
  311. gen->size(d->thread_count);
  312. gen->flags(flags);
  313. if(flags & app::prepopulated)
  314. gen->prepopulate(*srv_);
  315. booster::unique_lock<booster::recursive_mutex> lock(d->lock);
  316. d->apps.push_back(_data::attachment(gen,point));
  317. }
  318. void applications_pool::mount(booster::shared_ptr<application_specific_pool> gen,int flags)
  319. {
  320. mount(gen,mount_point(),flags);
  321. }
  322. booster::shared_ptr<application_specific_pool>
  323. applications_pool::get_application_specific_pool(char const *host,char const *script_name,char const *path_info,std::string &match)
  324. {
  325. booster::unique_lock<booster::recursive_mutex> lock(d->lock);
  326. for(std::list<_data::attachment>::iterator it = d->apps.begin();it!=d->apps.end();++it) {
  327. std::pair<bool,std::string> m = it->mp.match(host,script_name,path_info);
  328. if(!m.first)
  329. continue;
  330. match = m.second;
  331. return it->pool;
  332. }
  333. booster::shared_ptr<application_specific_pool> result;
  334. for(std::list<_data::attachment>::iterator itr = d->legacy_async_apps.begin();itr!=d->legacy_async_apps.end();) {
  335. std::list<_data::attachment>::iterator app_it = itr;
  336. ++itr;
  337. if(app_it->pool->flags() == -1) {
  338. d->legacy_async_apps.erase(app_it);
  339. }
  340. else if (!result) {
  341. std::pair<bool,std::string> m = app_it->mp.match(host,script_name,path_info);
  342. if(!m.first)
  343. continue;
  344. match = m.second;
  345. result = app_it->pool;
  346. }
  347. }
  348. return result;
  349. }
  350. booster::intrusive_ptr<application> applications_pool::get( char const *,
  351. char const *,
  352. char const *,
  353. std::string &)
  354. {
  355. throw cppcms_error("THIS IS INTERNAL MEMBER FUNCTION METHOD MUST NOT BE USED");
  356. }
  357. void applications_pool::put(application *)
  358. {
  359. BOOSTER_WARNING("cppcms") << "CALL OF INTERNAL METHOD";
  360. }
  361. } //cppcms