From 49595a8251899494b0d95c07911841acba47e1a8 Mon Sep 17 00:00:00 2001 From: Artyom Beilis Date: Sun, 8 Jun 2008 13:37:53 +0000 Subject: [PATCH] Merged cache brunch to trunk: 306:323 /framework/branches/cache --- Makefile.am | 4 +- archive.h | 74 ++++++++++++ base_cache.cpp | 41 +++++++ base_cache.h | 25 +++++ cache_interface.cpp | 141 +++++++++++++++++++++++ cache_interface.h | 45 ++++++++ cppcms_error.h | 15 +++ data.h | 77 ------------- global_config.cpp | 29 +++-- global_config.h | 23 ++-- http_error.h | 28 ----- main.cpp | 71 ------------ main_thread.cpp | 266 ------------------------------------------- main_thread.h | 64 ----------- templates.cpp | 231 -------------------------------------- templates.h | 128 --------------------- text_tool.cpp | 316 +--------------------------------------------------- text_tool.h | 27 +---- textstream.cpp | 25 ----- textstream.h | 39 ------- thread_cache.cpp | 268 ++++++++++++++++++++++++++++++++++++++++++++ thread_cache.h | 56 ++++++++++ thread_pool.cpp | 36 +++--- thread_pool.h | 101 +++++++++-------- url.cpp | 34 +++--- url.h | 32 +++--- worker_thread.cpp | 126 ++++++++++----------- worker_thread.h | 35 ++++-- 28 files changed, 898 insertions(+), 1459 deletions(-) create mode 100644 archive.h create mode 100644 base_cache.cpp create mode 100644 base_cache.h create mode 100644 cache_interface.cpp create mode 100644 cache_interface.h create mode 100644 cppcms_error.h delete mode 100644 data.h delete mode 100644 http_error.h delete mode 100644 main.cpp delete mode 100644 main_thread.cpp delete mode 100644 main_thread.h delete mode 100644 templates.cpp delete mode 100644 templates.h delete mode 100644 textstream.cpp delete mode 100644 textstream.h create mode 100644 thread_cache.cpp create mode 100644 thread_cache.h diff --git a/Makefile.am b/Makefile.am index 3eec9a2..88e5cc8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,6 @@ #test_fcgi_LDADD = libcppcms.la lib_LTLIBRARIES = libcppcms.la -libcppcms_la_SOURCES = FCgiIO.cpp global_config.cpp templates.cpp textstream.cpp thread_pool.cpp url.cpp worker_thread.cpp text_tool.cpp +libcppcms_la_SOURCES = FCgiIO.cpp global_config.cpp thread_pool.cpp url.cpp worker_thread.cpp text_tool.cpp cache_interface.cpp base_cache.cpp thread_cache.cpp -nobase_pkginclude_HEADERS = global_config.h templates.h text_tool.h url.h http_error.h textstream.h thread_pool.h worker_thread.h FCgiIO.h share/bytecode.h +nobase_pkginclude_HEADERS = global_config.h text_tool.h url.h cppcms_error.h thread_pool.h worker_thread.h FCgiIO.h cache_interface.h archive.h base_cache.h thread_cache.h diff --git a/archive.h b/archive.h new file mode 100644 index 0000000..a3eadc4 --- /dev/null +++ b/archive.h @@ -0,0 +1,74 @@ +#ifndef ARCHIVE_H +#define ARCHIVE_H +#include "cppcms_error.h" +#include +#include + +namespace cppcms { + +using namespace std; + +class archive { + string data; + size_t ptr; +public: + archive() { ptr=0; }; + archive(string const &s) : data(s) { ptr=0; }; + void set(string const &s) { data=s; ptr=0; }; + string const &get() const { return data; }; + template + archive &operator<<(T const &val) { + size_t size=sizeof(T); + data.append((char const *)&size,sizeof(size_t)); + data.append((char const *)&val,size); + return *this; + } + archive &operator<<(string const &val) { + size_t size=val.size(); + data.append((char const *)&size,sizeof(size_t)); + data.append(val.c_str(),size); + return *this; + } + template + archive &operator>>(T &val) + { + if(ptr+sizeof(size_t)+sizeof(T)>data.size()) { + throw cppcms_error("Format violation"); + } + char const *start=data.c_str()+ptr; + if(*(size_t const *)start!=sizeof(T)) { + throw cppcms_error("Invalid size read"); + } + start+=sizeof(size_t); + + memcpy(&val,start,sizeof(T)); + + ptr+=sizeof(size_t)+sizeof(T); + return *this; + } + archive &operator>>(string &val) + { + if(ptr+sizeof(size_t)>data.size()) { + throw cppcms_error("Format violation"); + } + char const *start=data.c_str()+ptr; + size_t s=*(size_t const *)start; + if(ptr+sizeof(size_t)+s>data.size()) { + throw cppcms_error("String too long"); + } + start+=sizeof(size_t); + val=string(start,s); + ptr+=sizeof(size_t)+s; + return *this; + } +}; + +class serializable { +public: + virtual void load(archive &a) = 0; + virtual void save(archive &a) const = 0; + virtual ~serializable() {}; +}; +} + +#endif diff --git a/base_cache.cpp b/base_cache.cpp new file mode 100644 index 0000000..f1bf476 --- /dev/null +++ b/base_cache.cpp @@ -0,0 +1,41 @@ +#include "base_cache.h" +namespace cppcms { + +using namespace std; + +bool base_cache::fetch_page(string const &key,string &output,bool gzip) +{ + return false; +} +bool base_cache::fetch(string const &key,archive &a,set &tags) +{ + return false; +}; + +void base_cache::clear() +{ + // Nothing +} +void base_cache::rise(string const &trigger) +{ + // Nothing +} + +void base_cache::store(string const &key,set const &triggers,time_t timeout,archive const &a) +{ + // Nothing +} + +base_cache::~base_cache() +{ + // Nothing +} + +void base_cache::stats(unsigned &keys,unsigned &triggers) +{ + keys=0; + triggers=0; +} + +} + diff --git a/base_cache.h b/base_cache.h new file mode 100644 index 0000000..1896ef2 --- /dev/null +++ b/base_cache.h @@ -0,0 +1,25 @@ +#ifndef BASE_CACHE_H +#define BASE_CACHE_H + +#include +#include +#include "archive.h" + +namespace cppcms { + +using namespace std; + +class base_cache { +public: + virtual bool fetch_page(string const &key,string &output,bool gzip); + virtual bool fetch(string const &key,archive &a,set &tags); + virtual void rise(string const &trigger); + virtual void clear(); + virtual void store(string const &key,set const &triggers,time_t timeout,archive const &a); + virtual void stats(unsigned &keys,unsigned &triggers); + virtual ~base_cache(); +}; + +} + +#endif diff --git a/cache_interface.cpp b/cache_interface.cpp new file mode 100644 index 0000000..dcea471 --- /dev/null +++ b/cache_interface.cpp @@ -0,0 +1,141 @@ +#include "cache_interface.h" +#include "worker_thread.h" +#include "global_config.h" +#include +#include +#include +#include + +namespace cppcms { +using namespace std; + +void deflate(string const &text,ostream &stream) +{ + using namespace boost::iostreams; + gzip_params params; + long level,length; + if((level=global_config.lval("gzip.level",-1))!=-1){ + params.level=level; + } + + filtering_ostream zstream; + + if((length=global_config.lval("gzip.buffer",-1))!=-1){ + zstream.push(gzip_compressor(params,length)); + } + else { + zstream.push(gzip_compressor(params)); + } + + zstream.push(stream); + zstream<caching_module) return false; + if(cms->caching_module->fetch_page(key,cms->out,cms->gzip)) { + cms->gzip_done=true; + return true; + } + return false; +} + +void cache_iface::store_page(string const &key,time_t timeout) +{ + if(!cms->caching_module) return; + archive a; + string compr=deflate(cms->out); + a<<(cms->out)<gzip){ + cms->out=compr; + cms->gzip_done=true; + } + cms->caching_module->store(key,triggers,timeout,a); +} + +void cache_iface::add_trigger(string const &t) +{ + if(!cms->caching_module) return; + triggers.insert(t); +} + +void cache_iface::rise(string const &t) +{ + if(!cms->caching_module) return; + cms->caching_module->rise(t); +} + +bool cache_iface::fetch_data(string const &key,serializable &data) +{ + if(!cms->caching_module) return false; + archive a; + set new_trig; + if(cms->caching_module->fetch(key,a,new_trig)) { + data.load(a); + triggers.insert(new_trig.begin(),new_trig.end()); + return true; + } + return false; +} + +void cache_iface::store_data(string const &key,serializable const &data, + set const &triggers, + time_t timeout) +{ + if(!cms->caching_module) return; + archive a; + data.save(a); + this->triggers.insert(triggers.begin(),triggers.end()); + cms->caching_module->store(key,triggers,timeout,a); +} + +bool cache_iface::fetch_frame(string const &key,string &result) +{ + if(!cms->caching_module) return false; + archive a; + set new_trig; + if(cms->caching_module->fetch(key,a,new_trig)) { + a>>result; + triggers.insert(new_trig.begin(),new_trig.end()); + return true; + } + return false; +} + +void cache_iface::store_frame(string const &key,string const &data, + set const &triggers, + time_t timeout) +{ + if(!cms->caching_module) return; + archive a; + a<triggers.insert(triggers.begin(),triggers.end()); + cms->caching_module->store(key,triggers,timeout,a); +} + +void cache_iface::clear() +{ + if(cms->caching_module) + cms->caching_module->clear(); +} + +bool cache_iface::stats(unsigned &k,unsigned &t) +{ + if(!cms->caching_module) + return false; + cms->caching_module->stats(k,t); + return true; +} + +} // End of namespace cppcms diff --git a/cache_interface.h b/cache_interface.h new file mode 100644 index 0000000..9ee784b --- /dev/null +++ b/cache_interface.h @@ -0,0 +1,45 @@ +#ifndef CACHE_IFACE_H +#define CACHE_IFACE_H + +#include +#include +#include "archive.h" + +using namespace std; + +namespace cppcms { + +const time_t infty=(sizeof(time_t)==4 ? 0x7FFFFFFF: 0x7FFFFFFFFFFFFFFFULL ); + +class worker_thread; +class cache_iface { + worker_thread *cms; + set triggers; +public: + void reset() { triggers.clear(); }; + cache_iface(worker_thread *w) : cms (w) {}; + bool fetch_page(string const &key); + void store_page(string const &key,time_t timeout=infty); + void rise(string const &trigger); + void add_trigger(string const &trigger); + bool fetch_frame(string const &key,string &result); + void store_frame(string const &key, + string const &frame, + set const &triggers=set(), + time_t timeout=infty); + bool fetch_data(string const &key,serializable &data); + void store_data(string const &key,serializable const &data, + set const &triggers=set(), + time_t timeout=infty); + void clear(); + bool stats(unsigned &keys,unsigned &triggers); + +}; + +void deflate(string const &text,ostream &stream); +string deflate(string const &text); + + +} + +#endif diff --git a/cppcms_error.h b/cppcms_error.h new file mode 100644 index 0000000..5a08e97 --- /dev/null +++ b/cppcms_error.h @@ -0,0 +1,15 @@ +#ifndef _HTTP_ERROR_H +#define _HTTP_ERROR_H + +#include +#include + +namespace cppcms { + +class cppcms_error : public std::runtime_error { +public: + cppcms_error(std::string const &error) : std::runtime_error(error) {}; +}; + +} +#endif /* _HTTP_ERROR_H */ diff --git a/data.h b/data.h deleted file mode 100644 index 189fde2..0000000 --- a/data.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// C++ Interface: data -// -// Description: -// -// -// Author: artik , (C) 2007 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#ifndef DATA_H -#define DATA_H - -#include "easy_bdb.h" - -using namespace ebdb; - -typedef varchar<32> username_t; -typedef varchar<16> password_t; - -struct user_t { - int id; - username_t username; - password_t password; -}; - -struct message_t { - int id; - int user_id; - long text_id; -}; - -class Users { -public: - typedef Index_Auto_Increment id_idx; - typedef id_idx::cursor_t id_c; - id_idx id; - - typedef Index_Var username_idx; - typedef username_idx::cursor_t username_c; - username_idx username; - Users(Environment &env) : - id(env,"users_id.db",DB_BTREE), - username(env,"users_username.db",DB_BTREE,&id) - {}; - void open() { id.open(); username.open();}; - void create() { id.create(); username.create();}; - void close() { id.close(); username.close();}; -}; - -class Messages { -public: - typedef Index_Auto_Increment id_idx; - typedef id_idx::cursor_t id_c; - id_idx id; - - Messages(Environment &env) : - id(env,"messages_id.db",DB_BTREE) - {}; - void open() { id.open();}; - void create() { id.create(); }; - void close() { id.close();}; -}; - - - - -extern auto_ptr users; -extern auto_ptr all_messages; -extern auto_ptr texts; - - - - -#endif diff --git a/global_config.cpp b/global_config.cpp index 7aa55bc..994b029 100644 --- a/global_config.cpp +++ b/global_config.cpp @@ -2,9 +2,12 @@ #include #include -Global_Config global_config; -bool Global_Config::get_tocken(FILE *f,tocken_t &T) +namespace cppcms { + +cppcms_config global_config; + +bool cppcms_config::get_tocken(FILE *f,tocken_t &T) { int c; while((c=fgetc(f))!=EOF) { @@ -52,7 +55,7 @@ bool Global_Config::get_tocken(FILE *f,tocken_t &T) } } if(T.second=="-" || T.second=="." || T.second=="-.") { - throw HTTP_Error("Illegal charrecters"); + throw cppcms_error("Illegal charrecters"); } if(c!=EOF) { ungetc(c,f); @@ -75,7 +78,7 @@ bool Global_Config::get_tocken(FILE *f,tocken_t &T) } } if(c==EOF){ - throw HTTP_Error("Unexpected EOF "); + throw cppcms_error("Unexpected EOF "); } if(c=='\n') line_counter++; if(c=='\"') { @@ -97,13 +100,13 @@ bool Global_Config::get_tocken(FILE *f,tocken_t &T) } else { - throw HTTP_Error(string("Unexpected charrecter")+(char)c); + throw cppcms_error(string("Unexpected charrecter")+(char)c); } } return false; } -void Global_Config::load(char const *fname) +void cppcms_config::load(char const *fname) { if(loaded){ return; @@ -111,7 +114,7 @@ void Global_Config::load(char const *fname) FILE *f=fopen(fname,"r"); line_counter=1; if(!f) { - throw HTTP_Error(string("Failed to open file:")+fname); + throw cppcms_error(string("Failed to open file:")+fname); } tocken_t T; string key; @@ -164,21 +167,21 @@ void Global_Config::load(char const *fname) } } if(state!=0) { - throw HTTP_Error("Parsing error"); + throw cppcms_error("Parsing error"); } } - catch (HTTP_Error &err){ + catch (cppcms_error &err){ fclose(f); char stmp[32]; snprintf(stmp,32," at line %d",line_counter); - throw HTTP_Error(string(err.get())+stmp); + throw cppcms_error(string(err.what())+stmp); } fclose(f); loaded=true; } -void Global_Config::load(int argc,char *argv[],char const *def) +void cppcms_config::load(int argc,char *argv[],char const *def) { if(loaded) { return; @@ -196,7 +199,9 @@ void Global_Config::load(int argc,char *argv[],char const *def) } } if(def_file==NULL) { - throw HTTP_Error("Configuration file not defined"); + throw cppcms_error("Configuration file not defined"); } load(def_file); } + +} diff --git a/global_config.h b/global_config.h index 5cae95d..dd37ce2 100644 --- a/global_config.h +++ b/global_config.h @@ -3,18 +3,19 @@ #include #include +#include "cppcms_error.h" -#include "http_error.h" +namespace cppcms { using namespace std; -class Global_Config { +class cppcms_config { enum { WORD, INT, DOUBLE, STR }; - typedef pair tocken_t; + typedef std::pair tocken_t; - typedef pair key_t; + typedef std::pair key_t; std::map long_map; std::map double_map; @@ -31,14 +32,13 @@ public: void load(char const *filename); void load(int argc,char *argv[],char const *def=NULL); - Global_Config() { loaded = false;}; - ~Global_Config() {}; + cppcms_config() { loaded = false;}; long lval(string major) { std::map::iterator it; if((it=long_map.find(major))!=long_map.end()) { return it->second; } - throw HTTP_Error("Undefined configuration "+major); + throw cppcms_error("Undefined configuration "+major); }; long lval(string major,long def) { std::map::iterator it; @@ -52,7 +52,7 @@ public: if((it=double_map.find(major))!=double_map.end()) { return it->second; } - throw HTTP_Error("Undefined configuration "+major); + throw cppcms_error("Undefined configuration "+major); }; double dval(string major,double def) { std::map::iterator it; @@ -66,7 +66,7 @@ public: if((it=string_map.find(major))!=string_map.end()) { return it->second; } - throw HTTP_Error("Undefined configuration "+major); + throw cppcms_error("Undefined configuration "+major); }; string sval(string major,string def){ std::map::iterator it; @@ -78,6 +78,9 @@ public: }; -extern Global_Config global_config; +extern cppcms_config global_config; + +} // namespace cppcms + #endif /* _GLOBAL_CONFIG_H */ diff --git a/http_error.h b/http_error.h deleted file mode 100644 index 86b21b5..0000000 --- a/http_error.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _HTTP_ERROR_H -#define _HTTP_ERROR_H - -#include -using namespace std; - -#define HTTP_ERROR_MAX_ERROR_MESSAGE_LEN 256 - - -class HTTP_Error { - bool State404; - char message[HTTP_ERROR_MAX_ERROR_MESSAGE_LEN]; -public: - char const *get() { return message; }; - bool is_404() { return State404; }; - HTTP_Error(char const *text,bool NotFound = false) - { - strncpy(message,text,HTTP_ERROR_MAX_ERROR_MESSAGE_LEN); - State404 = NotFound; - }; - HTTP_Error(string const &str,bool NotFound = false) - { - strncpy(message,str.c_str(),HTTP_ERROR_MAX_ERROR_MESSAGE_LEN); - State404 = NotFound; - }; -}; - -#endif /* _HTTP_ERROR_H */ diff --git a/main.cpp b/main.cpp deleted file mode 100644 index e7b18de..0000000 --- a/main.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include "main_thread.h" -#include "thread_pool.h" -#include "global_config.h" -#include "url.h" - -#include "templates.h" -#include "data.h" - -using namespace std; - -Templates_Set templates; - - -auto_ptr users; -auto_ptr all_messages; -auto_ptr texts; - -void setup() -{ - user_t user; - user.username="artik"; - user.password="artik"; - cerr<<"Setting up: "<id.add(user)<id.add(user); -} - -int main(int argc,char **argv) -{ - try{ - global_config.load(argc,argv); - - templates.load(); - - Environment env(global_config.sval( "bdb.path" ).c_str()); - users=auto_ptr(new Users(env)); - all_messages=auto_ptr(new Messages(env)); - texts=auto_ptr(new Texts_Collector(env,"texts.db")); - - env.create(); - - users->create(); - all_messages->create(); - texts->create(); - - - if(argc>2 && strcmp(argv[1],"setup")==0) { - setup(); - } - - Run_Application(argc,argv); - - users->close(); - all_messages->close(); - texts->close(); - env.close(); - - cout<<"Exiting\n"; - } - catch(HTTP_Error &s) { - cerr< &cookies = env->getCookieList(); - unsigned int i; - - username.clear(); - visitor.clear(); - email.clear(); - vurl.clear(); - password.clear(); - - for(i=0;iusername); - - if(cur==name){ - user_t const &user=cur; - if(user.password==password.c_str()) { - authenticated=true; - user_id=user.id; - } - username=name; - } - else { - username.clear(); - authenticated=false; - } - password.clear(); -} - -void Main_Thread::check_athentication() -{ - load_cookies(); - check_athentication_by_name(username,password); -} - -void Main_Thread::load_inputs() -{ - - const vector &elements=cgi->getElements(); - unsigned i; - - page=0; - message.clear(); - - for(i=0;isetCookie(cookie_u); - HTTPCookie cookie_p("password",new_password,"","",7*24*3600,"/",false); - response_header->setCookie(cookie_p); - } - else { - username=""; - password=""; - set_header(new HTTPRedirectHeader("/site/login")); - } -}; - -void Main_Thread::show_logout() -{ - set_header(new HTTPRedirectHeader("/site/")); - HTTPCookie cookie("username","","","",0,"/",false); - response_header->setCookie(cookie); - cookie.setName("password"); - cookie.setValue(""); - response_header->setCookie(cookie); -} - -void Main_Thread::show_main_page(string from) -{ - check_athentication(); - - Content c(T_VAR_NUM); - Renderer t(templates,TT_master,c); - - c[TV_title]="Main page"; - c[TV_show_content]=TT_main; - - if(authenticated) { - c[TV_username]=username; - } - - Messages::id_c cur(all_messages->id); - - if(from=="end") { - cur.end(); - } - else { - int from_id=atoi(from.c_str()); - curget(message.text_id,intext); - Text_Tool conv; - conv.markdown2html(intext,content); - - c[TV_message_body]=content.c_str(); - - Users::id_c ucur(users->id); - ucur==message.user_id; - user_t const &user=ucur; - c[TV_author]=user.username.c_str(); - cur.next(); - counter++; - } - else { - c[TV_new_message]=0; - } - } - } -} - -void Main_Thread::show_post_form() -{ - check_athentication(); - if(authenticated) { - Content c(T_VAR_NUM); - - c[TV_title]="New message"; - c[TV_show_content]=TT_post; - Renderer t(templates,TT_master,c); - while(t.render(out)); - } - else { - set_header(new HTTPRedirectHeader("/site/login")); - - } -} - -void Main_Thread::get_post_message() -{ - check_athentication(); - - load_inputs(); - - if(!authenticated){ - set_header(new HTTPRedirectHeader("/site/login")); - return; - } - - - message_t msg; - msg.text_id=texts->add(message); - msg.user_id=user_id; - all_messages->id.add(msg); - - set_header(new HTTPRedirectHeader("/site/")); -} - -void Main_Thread::show_page() -{ - url.parse(); -} -void Main_Thread::main() -{ - try { - show_page(); - } - catch (DbException &err) { - throw HTTP_Error(err.what()); - } - catch(char const *s) { - throw HTTP_Error(s); - } -} diff --git a/main_thread.h b/main_thread.h deleted file mode 100644 index f2acb4a..0000000 --- a/main_thread.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _MAIN_THREAD_H -#define _MAIN_THREAD_H - - -#include "worker_thread.h" -#include "http_error.h" - -#include -#include -#include "easy_bdb.h" -#include "data.h" - -using namespace cgicc; -using namespace ebdb; - -extern auto_ptr users; -extern auto_ptr all_messages; -extern auto_ptr texts; - - -class Main_Thread : public Worker_Thread { - URL_Parser url; -// User Data - int user_id; - string username; - string visitor; - string email; - string vurl; - string password; - bool authenticated; - string new_username; - string new_password; -// Other - int page; - string message; -// Functions - void show_page(); - void show_main_page(string from); - void show_login(); - void show_logout(); - void get_post_message(); - void load_cookies(); - void load_inputs(); - void do_login(); - void show_post_form(); - void edit_message(string s); -protected: - - void check_athentication(); - void check_athentication_by_name(string,string); - void get_parameters(); - - virtual void main(); - - string protect(string const &str); - -public: - virtual void init(); - Main_Thread() {}; - virtual ~Main_Thread() {}; -}; - - -#endif /* _MAIN_THREAD_H */ diff --git a/templates.cpp b/templates.cpp deleted file mode 100644 index 3235085..0000000 --- a/templates.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "templates.h" - -#include "global_config.h" - -#include -#include -#include -#include - -#include -using namespace std; - - -bool Renderer::debug_defined=false; -bool Renderer::debug=false; - -Renderer::Renderer(Templates_Set &tset,int id,Content &cont) -{ - if(!debug_defined) { - debug=global_config.lval("templates.debug_level",0); - debug_defined=true; - } - templates_set=&tset; - tmpl=tset.get(id); - if(!tmpl && debug) { - char buf[32]; - snprintf(buf,32,"%d",id); - throw HTTP_Error(string("Failed to load template")+buf); - } - pos=0; - stack_size=0; - content=&cont; - returns_stack.reserve(10); - templates_stack.reserve(10); -} - -int Renderer::render(string &s) -{ - if(!tmpl) return 0; - Content &cont=*content; - Base_Template *tmp_tmpl; - int templ_id; - for(;;) { - if(pos<0 || pos>(int64_t)(tmpl->len-sizeof(Tmpl_Op))){ - throw HTTP_Error("Template overflow"); - } - Tmpl_Op *op=(Tmpl_Op*)(tmpl->mem_ptr+pos); - pos+=sizeof(Tmpl_Op); - - Variable var; - - switch(op->opcode){ - case OP_VAR: - case OP_GOTO_IF_TRUE: - case OP_GOTO_IF_FALSE: - case OP_GOTO_IF_DEF: - case OP_GOTO_IF_NDEF: - case OP_INCLUDE_REF: - var=cont[op->parameter]; - break; - } - switch(op->opcode) { - case OP_INLINE: - if(pos+op->parameter>tmpl->len){ - throw HTTP_Error("Template overflow"); - } - s.append(tmpl->mem_ptr+pos, - op->parameter); - pos+=op->parameter; - break; - case OP_CALL: - return op->parameter; - case OP_VAR: - if(var.isstr()) { - s+=var.gets(); - } - else if(debug) { - throw HTTP_Error("Undefined variable"); - } - break; - case OP_INCLUDE_REF: - if(var.isint()){ - templ_id=var.geti(); - } - else { - throw HTTP_Error("Undefined variable in INCLUDE_REF"); - } - case OP_INCLUDE: - if(op->opcode==OP_INCLUDE){ - templ_id=op->parameter; - } - if((tmp_tmpl=templates_set->get(templ_id))==NULL){ - if(debug) - throw HTTP_Error("Undefined template"); - break; - } - if(returns_stack.size()<(unsigned)stack_size+1){ - returns_stack.push_back(pos); - templates_stack.push_back(tmpl); - } - else { - returns_stack[stack_size]=pos; - templates_stack[stack_size]=tmpl; - } - tmpl=tmp_tmpl; - stack_size++; - pos=0; - break; - case OP_GOTO_IF_TRUE: - if(var.isint()){ - if(var.geti()){ - pos=op->jump; - } - } - else if(debug){ - throw HTTP_Error("Undefined variable"); - } - break; - case OP_GOTO_IF_FALSE: - if(var.isint()){ - if(!var.geti()){ - pos=op->jump; - } - } - else if(debug){ - throw HTTP_Error("Undefined variable"); - } - break; - case OP_GOTO_IF_DEF: - if(var.isdef()){ - pos=op->jump; - } - break; - case OP_GOTO_IF_NDEF: - if(!var.isdef()){ - pos=op->jump; - } - break; - case OP_GOTO: - pos=op->jump; - break; - case OP_STOP: - if(stack_size==0){ - return 0; - } - stack_size--; - pos=returns_stack[stack_size]; - tmpl=templates_stack[stack_size]; - break; - default: - throw HTTP_Error("Unknown opcode"); - } - } -} - -void Templates_Set::load() -{ - load(global_config.sval("templates.file").c_str()); -} - -void Templates_Set::load(char const *file,int use_mmap) -{ - if(use_mmap==-1) { - use_mmap=global_config.lval("templates.use_mmap",0); - } - if(use_mmap) { - // Rationale: - // In case of many processes openning same file - struct stat statbuf; - char *buf; - if((fd=open(file,O_RDONLY))<0 - || fstat (fd,&statbuf) < 0 - || (buf=(char*)mmap(0,statbuf.st_size, - PROT_READ,MAP_SHARED, fd, 0))==(char*)-1) - { - throw HTTP_Error(string("Falied to open file:")+file); - } - file_size=statbuf.st_size; - base_ptr=buf; - } - else { - FILE *f; - f=fopen(file,"r"); - if(!f) { - throw HTTP_Error(string("Falied to open file:")+file); - } - fseek(f,0,SEEK_END); - file_size=ftell(f); - rewind(f); - char *buf=new char [file_size]; - base_ptr=buf; - if((int)fread(buf,1,file_size,f)!=file_size) { - fclose(f); - throw HTTP_Error(string("Falied to read file:")+file); - } - fclose(f); - } - setup_map(); -} - -void Templates_Set::setup_map() -{ - if(file_size<4) { - throw HTTP_Error("Incorrect file format"); - } - map_size=*(uint32_t*)base_ptr; - if(4+4*map_size>file_size || map_size<0){ - throw HTTP_Error("Incorrect file format"); - } - map=((uint32_t*)base_ptr)+1; - templates.reserve(map_size); - int offset=4+4*map_size; - int i; - for(i=0;ifile_size){ - HTTP_Error("Incorrect file format"); - } - templates.push_back(Base_Template(base_ptr+offset,map[i])); - offset+=map[i]; - } - if(offset!=file_size) - HTTP_Error("Incorrect file format"); -} - -Base_Template *Templates_Set::get(int id) -{ - if(id<0 || id>=map_size) { - return NULL; - } - return &(templates[id]); -} diff --git a/templates.h b/templates.h deleted file mode 100644 index e7561a5..0000000 --- a/templates.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef _TEMPLATES_H -#define _TEMPLATES_H - - -#include -#include -#include - -#include - -#include "share/bytecode.h" -#include "textstream.h" - -using namespace std; - - -class Variable { -public: - typedef enum { NONE, INTEGER, STRING } type_t; -private: - type_t type; - int int_val; - string str_data; -public: - Variable() { type = NONE; int_val=0; }; - Variable(string const &s) { - str_data=s; - type = STRING; - }; - Variable(int b) { int_val = b; type = INTEGER; }; - void operator=(int b) { *this=Variable(b); }; - void operator=(string const &s) { *this=Variable(s); }; - void reset() { str_data.empty(); type=NONE; }; - int geti() { return int_val; }; - char const *gets(){ return str_data.c_str(); }; - bool isstr() { return type == STRING; }; - bool isdef() { return type != NONE; }; - bool isint() { return type == INTEGER; }; - type_t get_type() { return type; }; -}; - -class Content { - int size; - vector vars; -public: - void reset() - { - int i; - for(i=0;isize=size; - vars.reserve(size); - reset(); - }; - Variable &operator[](int i) { - if(i<0 || i>=size) { - throw HTTP_Error("Out of content bounds"); - } - return vars[i]; - }; -}; - -class Base_Template { - friend class Renderer; - friend class Templates_Set; - - char const *mem_ptr; - int len; -public: - Base_Template() { mem_ptr=NULL;}; - Base_Template(char const *ptr, int l) { mem_ptr=ptr; len=l; }; -}; - -class Templates_Set { - friend class Base_Template; - char const *base_ptr; - vector templates; - uint32_t *map; - int map_size; - int file_size; - int fd; - void setup_map(void); -public: - Templates_Set() { - base_ptr=0; - map=0; - fd=-1; - }; - ~Templates_Set() { - if(fd!=-1){ - munmap((void*)base_ptr,file_size); - close(fd); - } - else { - delete [] base_ptr; - } - } - Base_Template *get(int id); - void load(char const *file,int use_mmap=-1); - void load(void); - -}; - -class Renderer { - static bool debug; - static bool debug_defined; - vector templates_stack; - vector returns_stack; - Templates_Set *templates_set; - int stack_size; - - Base_Template *tmpl; - int pos; - Content *content; -public: - Renderer(Templates_Set &tset,int id,Content &cont); - int render(string &s); - int render(Text_Stream &out) { return render(out.text);}; -}; - -extern Templates_Set templates; - - - -#endif /* _TEMPLATES_H */ diff --git a/text_tool.cpp b/text_tool.cpp index 95b8dc3..ffa751d 100644 --- a/text_tool.cpp +++ b/text_tool.cpp @@ -1,94 +1,13 @@ #include "text_tool.h" +using namespace std; +namespace cppcms{ +namespace texttool { -#include -#include -void Text_Tool::init() +void text2html(string const &s,string &content) { - ptr=0; -} - -void Text_Tool::getline(string &in) -{ - string tmp; - if(ptr==string::npos){ - input=L_EOF; - return; - } - size_t pos=in.find('\n',ptr); - if(pos==string::npos){ - if(ptr') { - to_html(tmp.substr(i+1)); - input=L_QUOTE; - return; - } - if(c=='-' && tmp[i+1]==' ') { - to_html(tmp.substr(i+2)); - input=L_UL; - return; - } - if(isdigit(c)) { - int p=i; - while(isdigit(tmp[p]))p++; - if(tmp[p]=='.' && tmp[p+1]==' ') { - to_html(tmp.substr(p+2)); - input=L_OL; - return; - } - } - if(c=='#') { - int p=i+1; - header_level=1; - while(tmp[p]=='#') { p++; header_level++;} - if(header_level>6) header_level=6; - to_html(tmp.substr(p)); - input=L_H; - return; - } - if(tmp.size()-i==0) { - input=L_BLANK; - return; - } - to_html(tmp); - input=L_TEXT; -} - -void Text_Tool::text2html(char const *s,string &content) -{ - int i; - content=""; - if(s==NULL) return; - int len=strlen(s); - content.reserve(len*3/2); - for(i=0;i': content+=">"; break; - case '&': content+="&"; break; - case '*': - if(s[i+1]!=' ' && (i>0 ? s[i-1]==' ':true) && !bold_on) { - content+=""; bold_on=true; last=B; - } - else if(bold_on && s[i+1]==' ') { - content+=""; bold_on=false; - } - else { - content+='*'; - } - break; - case '_': - if(s[i+1]!=' ' && (i>0 ? s[i-1]==' ':true) && !it_on) { - content+=""; it_on=true; last=I; - } - else if(it_on && s[i+1]==' ') { - content+=""; it_on=false; - } - else { - content+='_'; - } - break; - case '-': - if(s[i+1]=='-') { - i++; - content+="—"; - } - else content+="-"; - break; - case '\\': - if(s[i+1]=='\\') { - i++; - content+="
\n"; - } - else content+="\\"; - break; - case '[': - { - size_t p1,p2; - if((p1=s.find("](",i))!=string::npos - && (p2=s.find(")",p1))!=string::npos) - { - string text,url; - string otext=s.substr(i+1,p1-(i+1)); - string ourl=s.substr(p1+2,p2-(p1+2)); - text2html(otext,text); - text2url(ourl.c_str(),url); - content+=""; - content+=text; - content+=""; - i=p2; - } - else { - content+="["; - } - } - break; - default: - content+=c; - } - } - if(bold_on && it_on && last==I) { - content+=""; - it_on=false; - } - if(bold_on) { - content+=""; - } - if(it_on){ - content+=""; - } - content+="\n"; -} - -void Text_Tool::markdown2html(char const *c_in,string &out) -{ -#warning "Inefficient -- fix me" - string in=c_in; - init(); - out=""; - out.reserve(in.size()*3/2); - state=NOTHING; - while(state!=FINISH) { - getline(in); - switch(state) { - case NOTHING: break; - case QUOTE: - if(input!=L_QUOTE) { - out+="

\n"; - state=NOTHING; - } - else { - out+=content; - } - break; - case CODE: - if(input!=L_CODE) { - out+="\n"; - state=NOTHING; - } - else { - out+=content; - } - break; - case UL: - if(input==L_TEXT){ - out+=content; - } - else if(input==L_UL){ - out+="\n"; - out+="
  • \n"; - out+=content; - } - else { - out+="
  • \n"; - state=NOTHING; - } - break; - case OL: - if(input==L_TEXT){ - out+=content; - } - else if(input==L_OL){ - out+="\n"; - out+="
  • \n"; - out+=content; - } - else { - out+="
  • \n"; - state=NOTHING; - } - break; - case P: - if(input!=L_TEXT) { - out+="

    \n"; - state=NOTHING; - } - else { - out+=content; - } - break; - }; - if(state==NOTHING) { - switch(input){ - case L_BLANK: break; - case L_TEXT: - out+="

    \n"; - out+=content; - state=P; - break; - case L_H: - { - char buf[16]; - snprintf(buf,16,"",header_level); - out+=buf; - out+=content; - snprintf(buf,16,"\n",header_level); - out+=buf; - } - break; - case L_QUOTE: - out+="

    \n"; - out+=content; - state=QUOTE; - break; - case L_CODE: - out+="

    \n";
    -				out+=content;
    -				state=CODE;
    -				break;
    -			case L_UL:
    -				out+="
    • \n"; - out+=content; - state=UL; - break; - case L_OL: - out+="
      1. \n"; - out+=content; - state=OL; - break; - case L_EOF: - state=FINISH; - break; - } - } - } } diff --git a/text_tool.h b/text_tool.h index d019b31..cfef427 100644 --- a/text_tool.h +++ b/text_tool.h @@ -3,27 +3,12 @@ #include -using std::string; - -class Text_Tool { - // State definitions: - enum { NOTHING, QUOTE, CODE, UL, OL, P, FINISH }; - enum { L_BLANK, L_TEXT, L_H, L_QUOTE, L_CODE, L_UL, L_OL ,L_EOF }; - int state; - int input; - size_t ptr; - string content; - int header_level; - void getline(string &s); - void init(); - void to_html(string s); - void basic_to_html(string s); -public: - void markdown2html(char const *in,string &out); - void markdown2html(string &in,string &out) { markdown2html(in.c_str(),out);}; - void text2html(char const *s,string &); - void text2html(string &s,string &out) { text2html(s.c_str(),out);}; - void text2url(char const *s,string &); +namespace cppcms { + namespace texttool { + using std::string; + void text2html(string const &s,string &out); + void text2url(string const &s,string &out); + }; }; diff --git a/textstream.cpp b/textstream.cpp deleted file mode 100644 index 5b1612c..0000000 --- a/textstream.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "textstream.h" -#include -#include - - -void Text_Stream::printf(char *format,...) -{ - va_list ap; - - va_start(ap,format); - int size=vsnprintf(buffer,TS_BUFFER_SIZE,format,ap); - va_end(ap); - - if(size>TS_BUFFER_SIZE) { - char *str=new char[size+1]; - va_start(ap,format); - vsnprintf(str,size+1,format,ap); - va_end(ap); - text += str; - delete [] str; - } - else { - text += buffer; - } -} diff --git a/textstream.h b/textstream.h deleted file mode 100644 index 2814a93..0000000 --- a/textstream.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _TEXTSTREAM_H -#define _TEXTSTREAM_H - -#include - -#include "global_config.h" - -using namespace std; - -#define TS_BUFFER_SIZE 1024 -#define TS_INITAL_ALLOCATION 0x10000 - - -class Text_Stream { - int inital_alloc; - char buffer[TS_BUFFER_SIZE]; - string text; - friend class Renderer; -public: - void reset(void) { - text.clear(); - text.reserve(inital_alloc); - }; - Text_Stream() { - inital_alloc=global_config.lval("performance.textalloc", - TS_INITAL_ALLOCATION); - reset(); - }; - ~Text_Stream() {}; - void puts(char const *t) { text += t; }; - void putchar(char c) { text += c; }; - char const *get() { return text.c_str(); }; - string &getstring() { return text; }; - int len() { return text.size(); }; - void printf(char *format, ...); - void puts(string &str) { text += str; }; -}; - -#endif /* _TEXTSTREAM_H */ diff --git a/thread_cache.cpp b/thread_cache.cpp new file mode 100644 index 0000000..14da9f5 --- /dev/null +++ b/thread_cache.cpp @@ -0,0 +1,268 @@ +#include "thread_cache.h" +#include +#include + +using boost::format; +using boost::str; + +namespace cppcms { + +class mutex_lock { + pthread_mutex_t &m; +public: + mutex_lock(pthread_mutex_t &p): m(p) { pthread_mutex_lock(&m); }; + ~mutex_lock() { pthread_mutex_unlock(&m); }; +}; + +class rwlock_rdlock { + pthread_rwlock_t &m; +public: + rwlock_rdlock(pthread_rwlock_t &p): m(p) { pthread_rwlock_rdlock(&m); }; + ~rwlock_rdlock() { pthread_rwlock_unlock(&m); }; +}; + +class rwlock_wrlock { + pthread_rwlock_t &m; +public: + rwlock_wrlock(pthread_rwlock_t &p): m(p) { pthread_rwlock_wrlock(&m); }; + ~rwlock_wrlock() { pthread_rwlock_unlock(&m); }; +}; + +thread_cache::~thread_cache() +{ + pthread_mutex_destroy(&lru_mutex); + pthread_rwlock_destroy(&access_lock); +} + +string *thread_cache::get(string const &key,set *triggers) +{ + pointer p; + time_t now; + time(&now); + if(debug_mode) print_all(); + if((p=primary.find(key))==primary.end() || p->second.timeout->first < now) { + if(debug_mode) { + string res; + if(p==primary.end()) { + res=str(boost::format("Not found [%1%]\n") % key); + } + else { + res=str(boost::format("Found [%1%] but timeout of %2% seconds\n") + % key % (now - p->second.timeout->first)); + } + write(fd,res.c_str(),res.size()); + } + return NULL; + } + if(triggers) { + list::iterator tp; + for(tp=p->second.triggers.begin();tp!=p->second.triggers.end();tp++) { + triggers->insert((*tp)->first); + } + } + { + mutex_lock lock(lru_mutex); + lru.erase(p->second.lru); + lru.push_front(p); + p->second.lru=lru.begin(); + } + if(debug_mode){ + string res=str(boost::format("Fetched [%1%] triggers:") % key); + list::iterator tp; + for(tp=p->second.triggers.begin(); + tp!=p->second.triggers.end();tp++) + { + res+=(*tp)->first; + res+=" "; + } + res+="\n"; + write(fd,res.c_str(),res.size()); + } + return &(p->second.data); +} + +bool thread_cache::fetch_page(string const &key,string &out,bool gzip) +{ + rwlock_rdlock lock(access_lock); + string *r=get(key,NULL); + if(!r) return false; + size_t size=r->size(); + size_t s; + char const *ptr=r->c_str(); + if(sizesize-sizeof(size_t)) + return false; + if(!gzip){ + out.assign(ptr+sizeof(size_t),s); + } + else { + ptr+=s+sizeof(size_t); + size-=s+sizeof(size_t); + if(size &tags) +{ + rwlock_rdlock lock(access_lock); + string *r=get(key,&tags); + if(!r) return false; + a.set(*r); + return true; +} + +void thread_cache::clear() +{ + rwlock_wrlock lock(access_lock); + timeout.clear(); + lru.clear(); + primary.clear(); + triggers.clear(); +} +void thread_cache::stats(unsigned &keys,unsigned &triggers) +{ + rwlock_rdlock lock(access_lock); + keys=primary.size(); + triggers=this->triggers.size(); +} + +void thread_cache::rise(string const &trigger) +{ + rwlock_wrlock lock(access_lock); + if(debug_mode) print_all(); + pair range=triggers.equal_range(trigger); + triggers_ptr p; + list kill_list; + for(p=range.first;p!=range.second;p++) { + kill_list.push_back(p->second); + } + list::iterator lptr; + if(debug_mode){ + string out=str(boost::format("Trigger [%1%] dropping: ") % trigger); + write(fd,out.c_str(),out.size()); + } + + for(lptr=kill_list.begin();lptr!=kill_list.end();lptr++) { + if(debug_mode) { + write(fd,(*lptr)->first.c_str(),(*lptr)->first.size()); + write(fd," ",1); + } + delete_node(*lptr); + } + if(debug_mode) + write(fd,"\n",1); +} + +void thread_cache::store(string const &key,set const &triggers_in,time_t timeout_in,archive const &a) +{ + rwlock_wrlock lock(access_lock); + if(debug_mode) print_all(); + pointer main; + if(debug_mode) { + string res; + res=str(boost::format("Storing key [%1%], triggers:") % key); + for(set::iterator ps=triggers_in.begin(),pe=triggers_in.end();ps!=pe;ps++) { + res+=*ps; + res+=" "; + } + res+="\n"; + write(fd,res.c_str(),res.size()); + } + main=primary.find(key); + if(main==primary.end() && primary.size()>=limit && limit>0) { + if(debug_mode) { + char const *msg="Not found, size limit\n"; + write(fd,msg,strlen(msg)); + } + time_t now; + time(&now); + if(timeout.begin()->firstsecond; + if(debug_mode) { + string res; + res=str(boost::format("Deleting timeout node [%1%] with " + "delta of %2% seconds\n") % main->first + % (now - main->second.timeout->first)); + write(fd,res.c_str(),res.size()); + } + } + else { + main=lru.back(); + if(debug_mode) { + string res; + res=str(boost::format("Deleting LRU [%1%]\n") % main->first); + write(fd,res.c_str(),res.size()); + } + } + } + if(main!=primary.end()) + delete_node(main); + pair res=primary.insert(pair(key,container())); + main=res.first; + container &cont=main->second; + cont.data=a.get(); + lru.push_front(main); + cont.lru=lru.begin(); + cont.timeout=timeout.insert(pair(timeout_in,main)); + if(triggers_in.find(key)==triggers_in.end()){ + cont.triggers.push_back(triggers.insert(pair(key,main))); + } + set::const_iterator si; + for(si=triggers_in.begin();si!=triggers_in.end();si++) { + cont.triggers.push_back(triggers.insert(pair(*si,main))); + } +} + +void thread_cache::delete_node(pointer p) +{ + lru.erase(p->second.lru); + timeout.erase(p->second.timeout); + list::iterator i; + for(i=p->second.triggers.begin();i!=p->second.triggers.end();i++) { + triggers.erase(*i); + } + primary.erase(p); +} + +void thread_cache::print_all() +{ + string res; + res+="Printing stored keys\n"; + int N_triggers=0; + int N_keys=0; + time_t now; + time(&now); + for(pointer p=primary.begin();p!=primary.end();p++) { + N_keys++; + res+=str(boost::format("%1%: timeount in %2% sec, triggers:") % p->first + % (p->second.timeout->first - now)); + for(list::iterator p1=p->second.triggers.begin(), + p2=p->second.triggers.end(); + p2!=p1;p1++) + { + N_triggers++; + res+=(*p1)->first; + res+=" "; + } + res+="\n"; + } + res+="LRU order:"; + for(list::iterator pl=lru.begin();pl!=lru.end();pl++) { + res+=(*pl)->first; + res+=" "; + } + res+="\n"; + if(N_keys!=timeout.size() || N_keys!=lru.size() || N_triggers!=triggers.size()){ + res+=str(boost::format("Internal error #prim=%1%, #lru=%2%, " + "#prim.triggers=%3% #triggers=%4%\n") + % N_keys % lru.size() % N_triggers % triggers.size()); + } + else { + res+=str(boost::format("#Keys=%1% #Triggers=%2%\n") % N_keys % N_triggers); + } + write(fd,res.c_str(),res.size()); +} + +}; diff --git a/thread_cache.h b/thread_cache.h new file mode 100644 index 0000000..40db690 --- /dev/null +++ b/thread_cache.h @@ -0,0 +1,56 @@ +#ifndef THREAD_CHACHE_H +#define THREAD_CHACHE_H +#include "base_cache.h" +#include "pthread.h" +#include +#include +namespace cppcms { + +using namespace std; + +class thread_cache : public base_cache { + pthread_mutex_t lru_mutex; + pthread_rwlock_t access_lock; + struct container { + string data; + typedef map::iterator pointer; + list::iterator lru; + list::iterator> triggers; + multimap::iterator timeout; + }; + typedef container::pointer pointer; + map primary; + multimap triggers; + typedef multimap::iterator triggers_ptr; + multimap timeout; + typedef multimap::iterator timeout_ptr; + list lru; + typedef list::iterator lru_ptr; + unsigned limit; + + string *get(string const &key,set *triggers); + void delete_node(pointer p); + void print_all(); + bool debug_mode; + int fd; + +public: + void set_debug_mode(int fd) { debug_mode=true; this->fd=fd; }; + thread_cache(unsigned pages=0) : limit(pages) { + pthread_mutex_init(&lru_mutex,NULL); + pthread_rwlock_init(&access_lock,NULL); + debug_mode=false; + }; + void set_size(unsigned l) { limit=l; }; + virtual bool fetch_page(string const &key,string &output,bool gzip); + virtual bool fetch(string const &key,archive &a,set &tags); + virtual void rise(string const &trigger); + virtual void clear(); + virtual void stats(unsigned &keys,unsigned &triggers); + virtual void store(string const &key,set const &triggers,time_t timeout,archive const &a); + virtual ~thread_cache(); +}; + +} + +#endif diff --git a/thread_pool.cpp b/thread_pool.cpp index a0fc2d7..97baf15 100644 --- a/thread_pool.cpp +++ b/thread_pool.cpp @@ -3,11 +3,13 @@ #include #include +using namespace cppcms; +using namespace cppcms::details; -FastCGI_Application *FastCGI_Application::handlers_owner=NULL; +fast_cgi_application *fast_cgi_application::handlers_owner=NULL; -FastCGI_Application::FastCGI_Application(const char *socket,int backlog) +fast_cgi_application::fast_cgi_application(const char *socket,int backlog) { FCGX_Init(); @@ -19,14 +21,14 @@ FastCGI_Application::FastCGI_Application(const char *socket,int backlog) this->socket=socket; main_fd=FCGX_OpenSocket(socket,backlog); if(main_fd<0) { - throw HTTP_Error(string("Failed to open socket ") + throw cppcms_error(string("Failed to open socket ") +socket); } } } -FastCGI_Application::event_t FastCGI_Application::wait() +fast_cgi_application::event_t fast_cgi_application::wait() { for(;;) { struct pollfd fds[2]; @@ -54,22 +56,22 @@ FastCGI_Application::event_t FastCGI_Application::wait() } } -void FastCGI_Application::shutdown() +void fast_cgi_application::shutdown() { // Rise exit signal on // the selfpipe write(signal_pipe[1],"0",1); } -void FastCGI_Application::handler(int id) +void fast_cgi_application::handler(int id) { - FastCGI_Application *ptr=FastCGI_Application::get_instance(); + fast_cgi_application *ptr=fast_cgi_application::get_instance(); if(ptr) { ptr->shutdown(); } } -void FastCGI_Application::set_signal_handlers() +void fast_cgi_application::set_signal_handlers() { handlers_owner=this; /* Signals defined by standard */ @@ -78,14 +80,14 @@ void FastCGI_Application::set_signal_handlers() /* Additional signal */ signal(SIGINT,handler); } -void FastCGI_Single_Threaded_App::setup(Worker_Thread *worker) +void fast_cgi_single_threaded_app::setup(worker_thread *worker) { this->worker=worker; worker->init(); FCGX_InitRequest(&request, main_fd, 0); } -bool FastCGI_Single_Threaded_App::run() +bool fast_cgi_single_threaded_app::run() { // Blocking loop event_t event=wait(); @@ -110,7 +112,7 @@ bool FastCGI_Single_Threaded_App::run() }; -void FastCGI_Application::execute() +void fast_cgi_application::execute() { set_signal_handlers(); @@ -119,12 +121,12 @@ void FastCGI_Application::execute() } } -void *FastCGI_Mutiple_Threaded_App::thread_func(void *p) +void *fast_cgi_multiple_threaded_app::thread_func(void *p) { info_t *params=(info_t *)p; int id=params->first; - FastCGI_Mutiple_Threaded_App *me=params->second; + fast_cgi_multiple_threaded_app *me=params->second; FCGX_Request *req; @@ -136,7 +138,7 @@ void *FastCGI_Mutiple_Threaded_App::thread_func(void *p) return NULL; } -void FastCGI_Mutiple_Threaded_App::start_threads() +void fast_cgi_multiple_threaded_app::start_threads() { int i; @@ -152,7 +154,7 @@ void FastCGI_Mutiple_Threaded_App::start_threads() } } -void FastCGI_Mutiple_Threaded_App::wait_threads() +void fast_cgi_multiple_threaded_app::wait_threads() { int i; for(i=0;i #include #include #include "worker_thread.h" +#include "global_config.h" +namespace cppcms { -class FastCGI_Application { +namespace details { - FastCGI_Application static *handlers_owner; +class fast_cgi_application { + + fast_cgi_application static *handlers_owner; protected: // General control @@ -24,40 +28,40 @@ protected: typedef enum { EXIT , ACCEPT } event_t; event_t wait(); void set_signal_handlers(); - static FastCGI_Application *get_instance() { return handlers_owner; }; + static fast_cgi_application *get_instance() { return handlers_owner; }; public: - FastCGI_Application(char const *socket,int backlog); - virtual ~FastCGI_Application() {}; + fast_cgi_application(char const *socket,int backlog); + virtual ~fast_cgi_application() {}; void shutdown(); virtual bool run() { return false; }; void execute(); }; -class FastCGI_Single_Threaded_App : public FastCGI_Application { +class fast_cgi_single_threaded_app : public fast_cgi_application { /* Single thread model -- one process runs */ FCGX_Request request; - Worker_Thread *worker; - void setup(Worker_Thread *worker); + worker_thread *worker; + void setup(worker_thread *worker); public: virtual bool run(); - FastCGI_Single_Threaded_App(Worker_Thread *worker,char const *socket=NULL) - : FastCGI_Application(socket,1) { setup(worker); }; - virtual ~FastCGI_Single_Threaded_App(){}; + fast_cgi_single_threaded_app(worker_thread *worker,char const *socket=NULL) + : fast_cgi_application(socket,1) { setup(worker); }; + virtual ~fast_cgi_single_threaded_app(){}; }; template -class FastCGI_ST : public FastCGI_Single_Threaded_App { - Worker_Thread *worker_thread; +class fast_cgi_st : public fast_cgi_single_threaded_app { + worker_thread *wt; public: - FastCGI_ST(char const *socket=NULL) : - FastCGI_Single_Threaded_App((worker_thread=new WT) ,socket) {}; - virtual ~FastCGI_ST(){ delete worker_thread; }; + fast_cgi_st(char const *socket=NULL) : + fast_cgi_single_threaded_app((wt=new WT) ,socket) {}; + virtual ~fast_cgi_st(){ delete wt; }; }; template -class Safe_Set { +class sefe_set { pthread_mutex_t access_mutex; pthread_cond_t new_data_availible; pthread_cond_t new_space_availible; @@ -76,8 +80,8 @@ public: this->size=0; }; - Safe_Set() {}; - virtual ~Safe_Set() {}; + sefe_set() {}; + virtual ~sefe_set() {}; virtual void push(T val) { pthread_mutex_lock(&access_mutex); while(size>=max) { @@ -100,7 +104,7 @@ public: }; template -class Safe_Queue : public Safe_Set{ +class sefe_queue : public sefe_set{ T *queue; int head; int tail; @@ -121,25 +125,25 @@ public: void init(int size) { if(queue) return; queue=new T [size]; - Safe_Set::init(size); + sefe_set::init(size); } - Safe_Queue() { queue = NULL; head=tail=0; }; - virtual ~Safe_Queue() { delete [] queue; }; + sefe_queue() { queue = NULL; head=tail=0; }; + virtual ~sefe_queue() { delete [] queue; }; }; -class FastCGI_Mutiple_Threaded_App : public FastCGI_Application { +class fast_cgi_multiple_threaded_app : public fast_cgi_application { int size; long long int *stats; - Worker_Thread **workers; + worker_thread **workers; FCGX_Request *requests; - Safe_Queue requests_queue; - Safe_Queue jobs_queue; + sefe_queue requests_queue; + sefe_queue jobs_queue; - void setup(int size,int buffer_len,Worker_Thread **workers); + void setup(int size,int buffer_len,worker_thread **workers); pthread_t *pids; - typedef pair info_t; + typedef pair info_t; info_t *threads_info; @@ -147,16 +151,16 @@ class FastCGI_Mutiple_Threaded_App : public FastCGI_Application { void start_threads(); void wait_threads(); public: - FastCGI_Mutiple_Threaded_App( int num, + fast_cgi_multiple_threaded_app( int num, int buffer_len, - Worker_Thread **workers, + worker_thread **workers, char const *socket=NULL) : - FastCGI_Application(socket,num+1+buffer_len) + fast_cgi_application(socket,num+1+buffer_len) { setup(num,num+1+buffer_len,workers); }; virtual bool run(); - virtual ~FastCGI_Mutiple_Threaded_App() { + virtual ~fast_cgi_multiple_threaded_app() { delete [] requests; delete [] pids; delete [] threads_info; @@ -166,45 +170,50 @@ public: }; template -class FastCGI_MT : public FastCGI_Mutiple_Threaded_App { +class fast_cgi_mt : public fast_cgi_multiple_threaded_app { WT *threads; - Worker_Thread **ptrs; + worker_thread **ptrs; - Worker_Thread **setptrs(int num) + worker_thread **setptrs(int num) { threads = new WT [num]; - ptrs= new Worker_Thread* [num] ; + ptrs= new worker_thread* [num] ; for(int i=0;i -void Run_Application(int argc,char *argv[]) +void run_application(int argc,char *argv[]) { + using namespace details; + int n,max; global_config.load(argc,argv); char const *socket=global_config.sval("server.socket","").c_str(); if((n=global_config.lval("server.threads",0))==0) { - auto_ptr > app(new FastCGI_ST(socket)); + auto_ptr > app(new fast_cgi_st(socket)); app->execute(); } else { max=global_config.lval("server.buffer",1); - auto_ptr > app(new FastCGI_MT(n,max,socket)); + auto_ptr > app(new fast_cgi_mt(n,max,socket)); app->execute(); } }; -#endif /* _THREAD_PULL_H */ +} +#endif /* _THREAD_POOL_H */ diff --git a/url.cpp b/url.cpp index cee410c..172d160 100644 --- a/url.cpp +++ b/url.cpp @@ -4,8 +4,8 @@ using namespace std; using namespace boost; - -URL_Parser::~URL_Parser() +using namespace cppcms; +url_parser::~url_parser() { unsigned i; for(i=0;iconnect(callback); url_def.pattern=regex(exp); - url_def.type=URL_Def::CALLBACK; + url_def.type=url_def::CALLBACK; url_def.id=0; url_def.callback=signal; url_def.url=NULL; @@ -56,7 +56,7 @@ void URL_Parser::add(char const *exp,callback_t callback) } -int URL_Parser::parse(string &query) +int url_parser::parse(string &query) { unsigned i; for(i=0;iparse(tmp); - case URL_Def::CALLBACK: + case url_def::CALLBACK: (*patterns[i].callback)(result[1],result[2], result[3],result[4], result[5],result[6], @@ -82,7 +82,7 @@ int URL_Parser::parse(string &query) return -1; } -int URL_Parser::parse() +int url_parser::parse() { string query; if(worker){ @@ -94,7 +94,7 @@ int URL_Parser::parse() return parse(query); } -string URL_Parser::operator[](int i) +string url_parser::operator[](int i) { return result[i]; } diff --git a/url.h b/url.h index 7dba2bf..fad6a7d 100644 --- a/url.h +++ b/url.h @@ -10,8 +10,6 @@ // Some defines: -#define BIND boost::bind - #define $0 _9 #define $1 _1 #define $2 _2 @@ -22,45 +20,49 @@ #define $7 _7 #define $8 _8 +namespace cppcms { + +class worker_thread; -class Worker_Thread; using std::string; + typedef boost::signal callback_signal_t; typedef callback_signal_t::slot_type callback_t; -class URL_Parser; +class url_parser; -struct URL_Def { +struct url_def { boost::regex pattern; enum { ID, CALLBACK , URL } type; int id; - URL_Parser *url; + url_parser *url; callback_signal_t *callback; - URL_Def() { callback=NULL; }; + url_def() { callback=NULL; }; }; -class URL_Parser { - std::vectorpatterns; - Worker_Thread *worker; +class url_parser { + std::vectorpatterns; + worker_thread *worker; boost::cmatch result; void set_regex(char const *r); public: static const int not_found=-1; static const int ok=0; - URL_Parser() {}; - URL_Parser(Worker_Thread * w) { worker=w;}; - ~URL_Parser(); + url_parser() {}; + url_parser(worker_thread * w) { worker=w;}; + ~url_parser(); void add(char const *exp,int id); - void add(char const *exp,URL_Parser &url); + void add(char const *exp,url_parser &url); void add(char const *exp,callback_t callback); - void init(Worker_Thread *w) { worker=w; }; + void init(worker_thread *w) { worker=w; }; int parse(); int parse(string &s); std::string operator[](int); }; +} // Namespace cppcms #endif /* _URL_H */ diff --git a/worker_thread.cpp b/worker_thread.cpp index e2bf840..9c584cd 100644 --- a/worker_thread.cpp +++ b/worker_thread.cpp @@ -1,106 +1,96 @@ #include "worker_thread.h" +#include "global_config.h" +#include "thread_cache.h" #include #include using namespace cgicc; +namespace cppcms { -Worker_Thread::Worker_Thread() +void worker_thread::main() { -} - -void Worker_Thread::main() -{ - out.puts("

        Hello World

        \n"); + out="

        Hello World

        \n"; } -void Worker_Thread::run(FCGX_Request *fcgi) +void worker_thread::run(FCGX_Request *fcgi) { -#ifdef FCGX_API_ACCEPT_ONLY_EXISTS - if(FCGX_Continue_r(fcgi)<0){ - return; - } -#endif - io = auto_ptr(new FCgiIO(*fcgi)); - cgi = auto_ptr( new Cgicc(&*io) ); + cgi = auto_ptr(new Cgicc(&*io)); env=&(cgi->getEnvironment()); + out.clear(); + out.reserve(global_config.lval("performance.textalloc",65500)); + cache.reset(); + set_header(new HTTPHTMLHeader); - + + gzip=gzip_done=false; + char *ptr; + if((ptr=FCGX_GetParam("HTTP_ACCEPT_ENCODING",fcgi->envp))!=NULL) { + if(strstr(ptr,"gzip")!=NULL) { + gzip=global_config.lval("gzip.enable",0); + } + } + try { /**********/ main(); /**********/ if(response_header.get() == NULL) { - throw HTTP_Error("Looks like a bug"); + throw cppcms_error("Looks like a bug"); } } - catch( HTTP_Error &error_message) { - int err_code; - out.reset(); - string msg; - if(error_message.is_404()) { - err_code=404; - msg="Not Found: "; - msg+=error_message.get(); - } - else { - err_code=500; - msg=error_message.get(); - } - set_header(new HTTPStatusHeader(err_code,msg)); - out.puts(msg.c_str()); + catch(cppcms_error const &e) { + string msg=e.what(); + set_header(new HTTPStatusHeader(500,msg)); + out="

        "+msg+"

        "; } - char *ptr; - - bool gzip=false; - if((ptr=FCGX_GetParam("HTTP_ACCEPT_ENCODING",fcgi->envp))!=NULL) { - if(strstr(ptr,"gzip")!=NULL) { - gzip=true; - } - } - - if(global_config.lval("gzip.enable",0)==0) { - gzip=false; - } - if(gzip) { - using namespace boost::iostreams; *io<<"Content-Encoding: gzip\r\n"; *io<<*response_header; - gzip_params params; - long level,length; - - if((level=global_config.lval("gzip.level",-1))!=-1){ - params.level=level; - } - - filtering_ostream zstream; - - if((length=global_config.lval("gzip.buffer",-1))!=-1){ - zstream.push(gzip_compressor(params,length)); - } - else { - zstream.push(gzip_compressor(params)); - } - - zstream.push(*io); - zstream< #include -#include "textstream.h" - #include "cgicc/Cgicc.h" #include "cgicc/HTTPHTMLHeader.h" #include "cgicc/HTTPStatusHeader.h" @@ -14,8 +12,13 @@ #include #include "FCgiIO.h" -#include "http_error.h" +#include "cppcms_error.h" #include "url.h" +#include "cache_interface.h" +#include "base_cache.h" + + +namespace cppcms { using namespace std; using cgicc::CgiEnvironment; @@ -24,29 +27,37 @@ using cgicc::Cgicc; using cgicc::HTTPHeader; - - -class Worker_Thread { -friend class URL_Parser; +class worker_thread { +friend class url_parser; +friend class cache_iface; protected: auto_ptrio; auto_ptr cgi; CgiEnvironment const *env; - Text_Stream out; auto_ptr response_header; void set_header(HTTPHeader*h){response_header=auto_ptr(h);}; virtual void main(); + + // Output and Cahce + + cache_iface cache; + base_cache *caching_module; + bool gzip; + bool gzip_done; + string out; + void init_internal(); public: int id; pthread_t pid; - void run(FCGX_Request *req); - Worker_Thread(); - virtual ~Worker_Thread(){ }; - virtual void init() { }; + worker_thread() : cache(this) { init_internal(); } ; + virtual ~worker_thread(); + virtual void init() {}; }; +} + #endif