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.
 
 
 
 
 
 

312 lines
8.3 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. #if defined(__sun)
  9. #define _POSIX_PTHREAD_SEMANTICS
  10. #endif
  11. #include "tcp_cache_server.h"
  12. #include "cache_storage.h"
  13. #ifndef CPPCMS_WIN32
  14. #include <signal.h>
  15. #include "daemonize.h"
  16. #endif
  17. #ifdef CPPCMS_WIN_NATIVE
  18. #include "winservice.h"
  19. #endif
  20. #include <iostream>
  21. #include <stdlib.h>
  22. #include <stdexcept>
  23. #include <booster/shared_ptr.h>
  24. #include <booster/intrusive_ptr.h>
  25. #include <booster/shared_object.h>
  26. #include <booster/thread.h>
  27. #include <booster/log.h>
  28. #include "base_cache.h"
  29. #include "logging.h"
  30. #include <cppcms/session_storage.h>
  31. #include <cppcms/json.h>
  32. #include <cppcms/service.h>
  33. #include <cppcms/cppcms_error.h>
  34. #ifdef CPPCMS_WIN_NATIVE
  35. #include "session_win32_file_storage.h"
  36. #include "winservice.h"
  37. #else
  38. #include "session_posix_file_storage.h"
  39. #endif
  40. #include "session_memory_storage.h"
  41. struct settings {
  42. std::string ip;
  43. int port;
  44. int threads;
  45. int gc;
  46. cppcms::json::value config;
  47. booster::shared_ptr<cppcms::sessions::session_storage_factory> sessions;
  48. booster::shared_object plugin;
  49. booster::intrusive_ptr<cppcms::impl::base_cache> cache;
  50. ~settings()
  51. {
  52. sessions.reset(); // ensure that sessions object is destroyed before shared object
  53. cache = 0;
  54. }
  55. settings(int argc,char **argv)
  56. {
  57. try {
  58. config = cppcms::service::load_settings(argc,argv);
  59. setup(config);
  60. }
  61. catch(cppcms::cppcms_error const &) {
  62. help();
  63. throw;
  64. }
  65. }
  66. void help()
  67. {
  68. std::cerr <<
  69. "usage: cppcms_scale [ -c config.js ] [ parameters ]\n"
  70. " -c config.js JSON, Configuration file, also parameters may\n"
  71. " be set via command line rather then the file\n"
  72. " --ip=IP IP to bind, default 0.0.0.0\n"
  73. " --port=N Port to bind, mandatory\n"
  74. " --threads=N Worker threads, default = # HW CPU\n"
  75. " --cache-limit=N The size of the cache in items\n"
  76. " --session-storage=(memory|files|external)\n"
  77. " Session storage module\n"
  78. " --session-gc=N The frequency of garbage collection\n"
  79. " --session-dir=/path The location of files for session storage\n"
  80. " --session-shared_object=/path\n"
  81. " The shared object/dll that is used as external\n"
  82. " storage"
  83. " --session-module=name\n"
  84. " The name of the module for example mymod for\n"
  85. " an external storage, renamed to shared object\n"
  86. " according to OS conventions, like libmymod.so\n"
  87. #ifndef CPPCMS_WIN32
  88. " --daemon-enable=(true|false)\n"
  89. " Run the process as daemon, default false\n"
  90. " --daemon-lock=/path Location of the lock file that keeps process pid\n"
  91. " --daemon-user=user User that the daemon should run under\n"
  92. " --daemon-group=grp Group that the daemon should run under\n"
  93. " --daemon-chroot=/path\n"
  94. " Run the service in chroot jain\n"
  95. " --daemon-fdlimit=N The limit of file descriptors for the service\n"
  96. #endif
  97. #ifdef CPPCMS_WIN_NATIVE
  98. " --winservice-mode=(install|uninstall)\n"
  99. " Install or uninstall windows service\n"
  100. " --winservice-name=XXX\n"
  101. " Name of windows service\n"
  102. " --winservice-display_name=XXX\n"
  103. " The service name shown in the UI\n"
  104. " --winservice-start=(auto|demand)\n"
  105. " Windows service start mode\n"
  106. " --winservice-user=XXX\n"
  107. " --winservice-password=XXX\n"
  108. " The user and password the service would run under\n"
  109. #endif
  110. << std::endl;
  111. }
  112. void setup(cppcms::json::value const &v)
  113. {
  114. ip=v.get("ip","0.0.0.0");
  115. port=v.get<int>("port");
  116. threads=v.get("threads",booster::thread::hardware_concurrency());
  117. int items = v.get("cache.limit",-1);
  118. if(items!=-1){
  119. cache = cppcms::impl::thread_cache_factory(items);
  120. }
  121. gc=v.get("session.gc",10);
  122. std::string stor = v.get("session.storage","");
  123. if(!stor.empty()) {
  124. #ifndef CPPCMS_NO_GZIP
  125. if(stor == "files") {
  126. std::string dir = v.get("session.dir","");
  127. #ifdef CPPCMS_WIN_NATIVE
  128. sessions.reset(new cppcms::sessions::session_file_storage_factory(dir));
  129. #else
  130. sessions.reset(new cppcms::sessions::session_file_storage_factory(dir,threads,1,false));
  131. #endif
  132. }
  133. else
  134. #endif //CPPCMS_NO_GZIP
  135. if(stor == "memory") {
  136. sessions.reset(new cppcms::sessions::session_memory_storage_factory());
  137. }
  138. else if(stor == "external") {
  139. std::string so = v.get<std::string>("session.shared_object","");
  140. std::string module = v.get<std::string>("session.module","");
  141. std::string entry_point = v.get<std::string>("session.entry_point","sessions_generator");
  142. if(so.empty() && module.empty())
  143. throw cppcms::cppcms_error(
  144. "session.storage=external "
  145. "and neither session.shared_object "
  146. "nor session.module is defined");
  147. if(!so.empty() && !module.empty())
  148. throw cppcms::cppcms_error(
  149. "both session.shared_object "
  150. "and session.module are defined");
  151. if(so.empty()) {
  152. so = booster::shared_object::name(module);
  153. }
  154. std::string error;
  155. if(!plugin.open(so,error)) {
  156. throw cppcms::cppcms_error("sessions_pool: failed to load shared object " + so + ": " + error);
  157. }
  158. cppcms::sessions::cppcms_session_storage_generator_type f=0;
  159. plugin.symbol(f,entry_point);
  160. sessions.reset(f(v.find("session.settings")));
  161. }
  162. else
  163. throw cppcms::cppcms_error("Unknown session.storage:"+stor);
  164. }
  165. if(!sessions && !cache) {
  166. throw cppcms::cppcms_error("Neither cache.limit nor session.storage is defined");
  167. }
  168. }
  169. };
  170. #if !defined(CPPCMS_WIN32)
  171. void main_posix(settings &par)
  172. {
  173. cppcms::impl::daemonizer demon(par.config);
  174. cppcms::impl::tcp_cache_service srv(
  175. par.cache,
  176. par.sessions,
  177. par.threads,
  178. par.ip,
  179. par.port,
  180. par.gc);
  181. // Wait for signals for exit
  182. sigset_t wait_mask;
  183. sigemptyset(&wait_mask);
  184. sigaddset(&wait_mask, SIGINT);
  185. sigaddset(&wait_mask, SIGQUIT);
  186. sigaddset(&wait_mask, SIGTERM);
  187. pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
  188. int sig = 0;
  189. sigwait(&wait_mask, &sig);
  190. BOOSTER_NOTICE("cppcms_scale")<<"Catch signal: exiting...";
  191. srv.stop();
  192. }
  193. #elif defined(CPPCMS_WIN_NATIVE)
  194. static booster::shared_ptr<cppcms::impl::tcp_cache_service> the_server;
  195. static settings *the_settings;
  196. static booster::mutex done_lock;
  197. static booster::condition_variable done_cond;
  198. static bool done;
  199. static void win_prepare()
  200. {
  201. BOOSTER_NOTICE("cppcms_scale")<<"Starting service...";
  202. settings &par = *the_settings;
  203. the_server.reset(
  204. new cppcms::impl::tcp_cache_service(
  205. par.cache,
  206. par.sessions,
  207. par.threads,
  208. par.ip,
  209. par.port,
  210. par.gc)
  211. );
  212. }
  213. static void win_stop()
  214. {
  215. booster::unique_lock<booster::mutex> guard(done_lock);
  216. done = true;
  217. done_cond.notify_all();
  218. }
  219. static void win_run()
  220. {
  221. {
  222. booster::unique_lock<booster::mutex> guard(done_lock);
  223. while(!done) {
  224. done_cond.wait(guard);
  225. }
  226. }
  227. BOOSTER_NOTICE("cppcms_scale")<<"Stopping service...";
  228. the_server->stop();
  229. the_server.reset();
  230. the_settings = 0;
  231. }
  232. void main_win(settings &par,int argc,char **argv)
  233. {
  234. using cppcms::impl::winservice;
  235. the_settings = &par;
  236. winservice::instance().prepare(win_prepare);
  237. winservice::instance().stop(win_stop);
  238. winservice::instance().exec(win_run);
  239. winservice::instance().run(par.config,argc,argv);
  240. }
  241. #endif
  242. #ifdef CPPCMS_WIN32
  243. void main_console(settings &par)
  244. {
  245. cppcms::impl::tcp_cache_service srv(
  246. par.cache,
  247. par.sessions,
  248. par.threads,
  249. par.ip,
  250. par.port,
  251. par.gc);
  252. std::cout << "Press any key to stop..." << std::flush;
  253. std::cin.get();
  254. srv.stop();
  255. }
  256. #endif
  257. int main(int argc,char **argv)
  258. {
  259. try
  260. {
  261. settings par(argc,argv);
  262. cppcms::impl::setup_logging(par.config);
  263. #ifndef CPPCMS_WIN32
  264. main_posix(par);
  265. #elif defined CPPCMS_WIN_NATIVE
  266. if(cppcms::impl::winservice::is_console(par.config))
  267. main_console(par);
  268. else
  269. main_win(par,argc,argv);
  270. #else // cygwin
  271. main_console(par);
  272. #endif
  273. }
  274. catch(std::exception const &e) {
  275. BOOSTER_ERROR("cppcms_scale")<<e.what()<<booster::trace(e);
  276. return 1;
  277. }
  278. return 0;
  279. }