Browse Source

Added external property for compilation

Added autotools support
The sustem moved to BerkeleyDB as DB layer
master
Artyom Beilis 16 years ago
parent
commit
0a97c23f69
12 changed files with 231 additions and 194 deletions
  1. +0
    -0
      COPYING
  2. +3
    -0
      Makefile.am
  3. +5
    -0
      config.txt
  4. +18
    -0
      configure.in
  5. +80
    -79
      easy_bdb.h
  6. +46
    -4
      main.cpp
  7. +61
    -58
      main_thread.cpp
  8. +14
    -4
      main_thread.h
  9. +0
    -42
      makefile
  10. +0
    -3
      templates.cpp
  11. +1
    -1
      templates.h
  12. +3
    -3
      tests/bdbtest.cpp

COPYRIGHT → COPYING View File


+ 3
- 0
Makefile.am View File

@@ -0,0 +1,3 @@
bin_PROGRAMS = test.fcgi
test_fcgi_SOURCES = FCgiIO.cpp global_config.cpp main.cpp main_thread.cpp templates.cpp textstream.cpp thread_pool.cpp url.cpp worker_thread.cpp


+ 5
- 0
config.txt View File

@@ -5,6 +5,11 @@ mysql.username="root"
mysql.password="root"
mysql.database="cppcms"


# Berkeley DB Parameters

bdb.path="./db/"

# FastCGI settings

server.threads = 5


+ 18
- 0
configure.in View File

@@ -0,0 +1,18 @@
dnl Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)

AC_INIT([test.fcgi], [0.0.1], [artyomtnk@yahoo.com])

AM_INIT_AUTOMAKE([1.9 foreign])

AC_PROG_CXX

AC_LANG_CPLUSPLUS
AC_CONFIG_FILES([Makefile])
AC_CHECK_LIB(db_cxx,main)
AC_CHECK_LIB(fcgi++,main)
AC_CHECK_LIB(cgicc,main)
AC_CHECK_LIB(boost_regex,main)
AC_CHECK_LIB(boost_signals,main)
AC_OUTPUT

+ 80
- 79
easy_bdb.h View File

@@ -22,14 +22,15 @@ public:
varchar(std::string const s) { set(s.c_str()); };
varchar &operator=(varchar &v) { set(v.data); return *this;};
varchar &operator=(char const *s) { set(s); return *this;};
operator char const *() { return data; };
operator std::string () { return std::string(data); };
bool operator<(char const *s) { return strcmp(data,s)<0; };
bool operator>(char const *s) { return strcmp(data,s)>0; };
bool operator==(char const *s) { return strcmp(data,s)==0; };
operator char const *() const { return data; };
char const *c_str() const { return data; };
operator std::string () const { return std::string(data); };
bool operator<(char const *s) const { return strcmp(data,s)<0; };
bool operator>(char const *s) const { return strcmp(data,s)>0; };
bool operator==(char const *s) const { return strcmp(data,s)==0; };
};
template<typename T1,typename T2>
struct Ord_Pair{
T1 first;
@@ -59,8 +60,8 @@ T2 second;
return first==s.first && second==s.second;
};
};
enum { SELECT_START,
SELECT_END,
SELECT_GT,
@@ -74,12 +75,12 @@ public:
DbEnv *env;
char *env_name;
public:
Environment(char *name) {
Environment(char const *name) {
env = new DbEnv(0);
env_name = new char [strlen(name)+1];
strcpy(env_name,name);
};
DbEnv *getenv() {
return env;
};
@@ -96,7 +97,7 @@ public:
delete [] env_name;
delete env;
};
};
};

template<class DS,typename E> class Index_Base;

@@ -110,7 +111,7 @@ class cursor {
dbt.set_ulen(sizeof(DS));
dbt.set_flags(DB_DBT_USERMEM);
};
void setup_dbt(Dbt &dbt,E &data)
{
dbt.set_data(&data);
@@ -136,32 +137,32 @@ public:
cursor(){
reset();
};
cursor(Index_Base<DS,E> &db) {
reset();
db.init_cursor(*this);
};
cursor(Db *db,int (*cmp)(void *,void *)) {
reset();
db->cursor(NULL,&cur,0);
cmp_fnc=cmp;
};
~cursor() {
if(cur) cur->close();
};

private:
private:
int select(int dir,DS &data)
{
E akey;
Dbt key,val;
Dbt key,val;
int res;
setup_dbt(val,data);
setup_dbt(key,akey);
switch(dir) {
case SELECT_START:
direction=1;
@@ -176,15 +177,15 @@ private:
}
return res;
}
int select(int dir,E const &in_key,DS &data){
E akey;
memcpy(&akey,&in_key,sizeof(E));
Dbt key,val;
Dbt key,val;
int res;
setup_dbt(val,data);
setup_dbt(key,akey);
switch(dir) {
@@ -205,12 +206,12 @@ private:
default:
throw "Incorrect cursor direction";
}
if(dir==SELECT_EQ) {
return cur->get(&key,&val,DB_SET);
}
res=cur->get(&key,&val,DB_SET_RANGE);
if(res){
if(dir == SELECT_LTE || dir == SELECT_LT) {
res=cur->get(&key,&val,DB_LAST);
@@ -218,13 +219,13 @@ private:
}
return res;
}
if(!cmp_fnc) {
return res;
}
int cmpres=cmp_fnc(&akey,&in_key);
if(cmpres==0 && dir == SELECT_LT)
{
return next(data,false);
@@ -243,19 +244,19 @@ private:
{
return next(data,true);
}
if(cmpres>0 && (dir == SELECT_LT || dir == SELECT_LTE) )
{
return next(data,false);
}
return res;
};
int curget(DS &data,int d)
{
E akey;
Dbt key,val;
Dbt key,val;
setup_dbt(val,data);
setup_dbt(key,akey);
return cur->get(&key,&val,d);
@@ -274,10 +275,10 @@ private:
return curget(data,d);
};

public:
public:
bool next() { return data_exist=(next(data)==0); };
bool operator++() { return data_exist=curget(data,DB_NEXT)==0;};
bool operator--() { return data_exist=curget(data,DB_PREV)==0;};
bool operator++(int) { return data_exist=curget(data,DB_NEXT)==0;};
@@ -314,7 +315,7 @@ public:
Dbt val(&data,sizeof(DS));
return data_exist=cur->put(&key,&val,DB_CURRENT)==0;
};
bool set(DS &data) {
bool tmp=*this=data;
if(tmp) {
@@ -370,7 +371,7 @@ protected:
public:
Db *get_primary_db() { return db_primary; };
Db *get_db() { return db; };
DB_Base(Environment &env,char *name,DBTYPE type,unique_t u = UNIQUE)
{
db = new Db(env.getenv(),0);
@@ -411,17 +412,17 @@ class Texts_Collector : public DB_Base
}
public:
Texts_Collector(Environment &env,char *name) :
DB_Base(env,name,DB_BTREE)
DB_Base(env,name,DB_BTREE)
{
db->set_bt_compare(cmp);
};
bool get(long id,std::string &s) {
Dbt key(&id,sizeof(long));
Dbt val;
val.set_flags(DB_DBT_MALLOC);
if(db->get(NULL,&key,&val,0)) {
return false;
}
@@ -429,39 +430,39 @@ public:
free(val.get_data());
return true;
};
bool put(long id,char const *text,int len=-1)
{
if(len<0)
if(len<0)
len=strlen(text);
Dbt data((void*)text,len+1);
Dbt key(&id,sizeof(long));
return db->put(NULL,&key,&data,0)==0;
};
bool put(long id,std::string const &s){
return put(id,s.c_str(),s.size());
};
long add(char const *text,int len=-1)
{
Dbc *cur;
db->cursor(NULL,&cur,0);
long id;
Dbt key;
key.set_data(&id);
key.set_ulen(sizeof(long));
key.set_flags(DB_DBT_USERMEM);
Dbt tmpdat;
char buf;
tmpdat.set_dlen(1);
tmpdat.set_doff(0);
tmpdat.set_data(&buf);
tmpdat.set_flags(DB_DBT_PARTIAL);
if(cur->get(&key,&tmpdat,DB_LAST)==DB_NOTFOUND) {
id=0;
}
@@ -493,7 +494,7 @@ public:
Dbt data((void*)text,len+1);
return db->put(NULL,&key,&data,0)==0;
};
bool update(long id,std::string const &s){
return update(id,s.c_str(),s.size());
};
@@ -508,7 +509,7 @@ protected:
dbt.set_ulen(sizeof(DS));
dbt.set_flags(DB_DBT_USERMEM);
};
void setup_dbt(Dbt &dbt,E &data)
{
dbt.set_data(&data);
@@ -524,18 +525,18 @@ public:
int flag=unique==UNIQUE ? DB_NOOVERWRITE : 0;
return this->db->put(NULL,&key,&val,flag)==0;
};
bool get(E k,DS &data) {
Dbt key(&k,sizeof(E));
Dbt val;
setup_dbt(val,data);
return db->get(NULL,&key,&val,0)==0;
};

Index_Base(Environment &env,char *name,DBTYPE type,
DB_Base *primary = NULL, unique_t u=UNIQUE)
DB_Base *primary = NULL, unique_t u=UNIQUE)
: DB_Base(env,name,type,u)
{
if(primary) {
@@ -545,10 +546,10 @@ public:
db_primary=NULL;
}
};
virtual ~Index_Base() {
};
static int keycmp(E &key1,E &key2)
{
int res;
@@ -571,31 +572,31 @@ public:
memcpy(&key2,dbt2->get_data(),sizeof(E));
return keycmp(key1,key2);
}
typedef cursor<DS,E> cursor_t;
static int cmpcur(void const *p1,void const *p2)
{
return keycmp(*(E*)p1,*(E*)p2);
}
virtual void init_cursor(cursor<DS,E> &cur) {
if(this->db_type == DB_BTREE) {
cur.cmp_fnc=cmpcur;
}
this->db->cursor(NULL,&cur.cur,0);
}
}
};

template<class DS,typename E,E (DS::*getmember)()>
class Index_Func: public Index_Base< DS , E > {
public:
virtual bool insert(DS &data) {
E keyval((data.*getmember)());
return Index_Base<DS,E>::insert(keyval,data);
};
static int get_key(Db *db, const Dbt *key,
const Dbt *data,Dbt *secondary_key)
{
@@ -603,13 +604,13 @@ public:
DS *d=(DS*)data->get_data();
E e_tmp=(d->*getmember)();
memcpy(ptr,&e_tmp,sizeof(E));
secondary_key->set_flags(DB_DBT_APPMALLOC);
secondary_key->set_data(ptr);
secondary_key->set_size(sizeof(E));
return 0;
}
static E extract_key(DS &d)
{
return (d.*getmember())();
@@ -638,20 +639,20 @@ public:

template<class DS,typename E,E DS::*member>
class Index_Var: public Index_Base< DS , E > {
public:
virtual bool insert(DS &data) {
E keyval(data.*member);
return Index_Base< DS , E >::insert(keyval,data);
};
static int get_key(Db *db, const Dbt *key,
const Dbt *data,Dbt *secondary_key)
{
DS *d=(DS*)data->get_data();
E *e_tmp=&(d->*member);
secondary_key->set_data(e_tmp);
secondary_key->set_size(sizeof(E));
return 0;
@@ -665,7 +666,7 @@ public:
Index_Base< DS , E >::init_cursor(cur);
cur.extract=extract_key;
};
Index_Var(Environment &env,char *name,
DBTYPE type,
DB_Base *primary = NULL,
@@ -687,7 +688,7 @@ class Index_Auto_Increment : public Index_Var <DS,E,member> {
public:
Index_Auto_Increment(Environment &env,char *name,
DBTYPE type,
DB_Base *primary = NULL) :
DB_Base *primary = NULL) :
Index_Var<DS,E,member>(env,name,type,primary,UNIQUE)
{
// Nothing
@@ -698,23 +699,23 @@ public:
this->db->cursor(NULL,&cur,0);
E id;
Dbt key;
key.set_data(&id);
key.set_ulen(sizeof(E));
key.set_flags(DB_DBT_USERMEM);
Dbt tmpdat;
char buf;
tmpdat.set_dlen(1);
tmpdat.set_doff(0);
tmpdat.set_data(&buf);
tmpdat.set_flags(DB_DBT_PARTIAL);
if(cur->get(&key,&tmpdat,DB_LAST)==DB_NOTFOUND) {
id=0;
}
while (true) {
id++;
(indata.*member)=id;
@@ -731,7 +732,7 @@ public:
cur->close();
return id;
};
};




+ 46
- 4
main.cpp View File

@@ -1,29 +1,71 @@
#include <iostream>
#include <memory>
#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> users;
auto_ptr<Messages> all_messages;
auto_ptr<Texts_Collector> texts;

void setup()
{
users_t user;
user.username="artik";
user.password="artkmst";
cerr<<"Setting up: "<<users->id.add(user)<<endl;
user.username="maas";
user.password="maas";
users->id.add(user);
}

int main(int argc,char **argv)
{
try{
global_config.load(argc,argv);
templates.load();
Run_Application<Main_Thread>(argc,argv);

Environment env(global_config.sval( "bdb.path" ).c_str());
users=auto_ptr<Users>(new Users(env));
all_messages=auto_ptr<Messages>(new Messages(env));
texts=auto_ptr<Texts_Collector>(new Texts_Collector(env,"tests.db"));

env.create();

users->create();
all_messages->create();
texts->create();


if(argc>2 && strcmp(argv[1],"setup")==0) {
setup();
}

Run_Application<Main_Thread>(argc,argv);

users->close();
all_messages->close();
texts->close();
env.close();

cout<<"Exiting\n";
}
catch(HTTP_Error &s) {
cerr<<s.get()<<endl;
return 1;
}
catch(DbException &e) {
cerr<<e.what()<<endl;
}
return 0;
}

+ 61
- 58
main_thread.cpp View File

@@ -4,6 +4,8 @@

#include "templates/look.h"
#include "templates.h"
#include "data.h"
#include "boost/format.hpp"

extern Templates_Set templates;

@@ -20,13 +22,6 @@ void Main_Thread::init()
url.add("^/dologin$", BIND(&Main_Thread::do_login,this));
url.add("^/edit/(\\d+)$",BIND(&Main_Thread::edit_message,this,$1));

try {
db.open();
}
catch(DB_Err &e)
{
throw HTTP_Error(e.get());
}
}

void Main_Thread::edit_message(string msg)
@@ -45,7 +40,7 @@ void Main_Thread::load_cookies()
email.clear();
vurl.clear();
password.clear();
for(i=0;i<cookies.size();i++) {
if(cookies[i].getName()=="username") {
username=cookies[i].getValue();
@@ -67,16 +62,13 @@ void Main_Thread::load_cookies()

void Main_Thread::check_athentication_by_name(string name,string password)
{
DB_Res res=db.query(
escape( "SELECT password,id from cp_users "
"WHERE username='%1%' LIMIT 1")<<name);
DB_Row row;
if((row=res.next())!=NULL){
if(password==row[0]) {
Users::username_c cur(users->username);

if(cur==name){
users_t const &user=cur;
if(user.password==password.c_str()) {
authenticated=true;
user_id=atoi(row[1]);
user_id=user.id;
}
username=name;
}
@@ -95,10 +87,10 @@ void Main_Thread::check_athentication()

void Main_Thread::load_inputs()
{
const vector<FormEntry> &elements=cgi->getElements();
unsigned i;
unsigned i;
page=0;
message.clear();

@@ -119,22 +111,22 @@ void Main_Thread::load_inputs()
void Main_Thread::show_login()
{
Content c(T_VAR_NUM);
c[TV_title]="Login";
c[TV_show_content]=TT_dologin;
Renderer r(templates,TT_master,c);
while(r.render(out)!=0);
}

void Main_Thread::do_login()
{
load_inputs();
check_athentication_by_name(new_username,new_password);
if(authenticated) {
set_header(new HTTPRedirectHeader("/site/"));
HTTPCookie cookie_u("username",username,"","",7*24*3600,"/",false);
@@ -164,7 +156,7 @@ void Main_Thread::text2html(char const *text,string &s)
int c;
s="";
s.reserve(strlen(text)*3/2);
while((c=*text++)!=0) {
switch(c) {
case '\n': s+="<br>\n"; break;
@@ -180,50 +172,53 @@ void Main_Thread::text2html(char const *text,string &s)
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;
}
DB_Res res;
Messages::id_c cur(all_messages->id);
if(from=="end") {
res = db.query(
"SELECT cp_messages.id,message,username "
"FROM cp_messages "
"LEFT JOIN cp_users ON cp_messages.user_id=cp_users.id "
"ORDER BY cp_messages.id DESC LIMIT 10");
cur.end();
}
else {
int from_id=atoi(from.c_str());
char const q[]=
"SELECT cp_messages.id,message,username "
"FROM cp_messages "
"LEFT JOIN cp_users ON cp_messages.user_id=cp_users.id "
"WHERE cp_messages.id < %1% "
"ORDER BY cp_messages.id DESC LIMIT 10";

res = db.query(escape(q)<<from_id);
cur<from_id;
}
DB_Row row;


int id;
string content;
int counter=0;
while((id=t.render(out))!=0) {
if(id==TV_get_message){
if((row=res.next())!=NULL){
if(cur && counter<10){
messages_t const &message=cur;
c[TV_new_message]=1;
c[TV_message_id]=row[0];
text2html(row[1],content);
char buf[20];
snprintf(buf,20,"%d",message.id);
c[TV_message_id]=buf;

string intext;

texts->get(message.text,intext);
text2html(intext.c_str(),content);

c[TV_message_body]=content.c_str();
c[TV_author]=row[2];

Users::id_c ucur(users->id);
ucur==message.user_id;
users_t const &user=ucur;
c[TV_author]=user.username.c_str();
cur.next();
counter++;
}
else {
c[TV_new_message]=0;
@@ -237,7 +232,7 @@ 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);
@@ -245,7 +240,7 @@ void Main_Thread::show_post_form()
}
else {
set_header(new HTTPRedirectHeader("/site/login"));
}
}

@@ -259,8 +254,13 @@ void Main_Thread::get_post_message()
set_header(new HTTPRedirectHeader("/site/login"));
return;
}
db.exec(escape("INSERT INTO cp_messages (message,user_id) values('%1%',%2%)")
<<message<<user_id);


messages_t msg;
msg.text=texts->add(message);
msg.user_id=user_id;
all_messages->id.add(msg);

set_header(new HTTPRedirectHeader("/site/"));
}

@@ -273,7 +273,10 @@ void Main_Thread::main()
try {
show_page();
}
catch (DB_Err &mysql_err) {
throw HTTP_Error(mysql_err.get());
catch (DbException &err) {
throw HTTP_Error(err.what());
}
catch(char const *s) {
throw HTTP_Error(s);
}
}

+ 14
- 4
main_thread.h View File

@@ -7,14 +7,24 @@

#include <cgicc/HTTPStatusHeader.h>
#include <cgicc/HTTPRedirectHeader.h>
#include "easy_bdb.h"
#include "data.h"

using namespace db_wrapper;
using namespace cgicc;
using namespace ebdb;



extern auto_ptr<Users> users;
extern auto_ptr<Messages> all_messages;
extern auto_ptr<Texts_Collector> texts;




class Main_Thread : public Worker_Thread {
URL_Parser url;
// Internal Data
Data_Base db;
// User Data
int user_id;
string username;
@@ -28,7 +38,7 @@ class Main_Thread : public Worker_Thread {
// Other
int page;
string message;
// Functions
// Functions
void show_page();
void show_main_page(string from);
void show_login();
@@ -41,7 +51,7 @@ class Main_Thread : public Worker_Thread {
void text2html(char const *text,string &s);
void edit_message(string s);
protected:
void check_athentication();
void check_athentication_by_name(string,string);
void get_parameters();


+ 0
- 42
makefile View File

@@ -1,42 +0,0 @@
TR=test.fcgi
SRC=main.cpp textstream.cpp worker_thread.cpp FCgiIO.cpp main_thread.cpp db_wrapper.cpp thread_pool.cpp \
global_config.cpp url.cpp templates.cpp

LSRC=textstream.cpp worker_thread.cpp FCgiIO.cpp mysql_db.cpp thread_pool.cpp global_config.cpp templates.cpp
OBJ := $(patsubst %.cpp,%.o,$(SRC))
LOBJ := $(patsubst %.cpp,%.o,$(LSRC))

LIBS = -lmysqlclient -lfcgi++ -lcgicc -lboost_regex -lboost_signals
CXX = g++
;CFLAGS = -Wall -g -DFCGX_API_ACCEPT_ONLY_EXISTS
CFLAGS = -Wall -g -O2 -I..


all: $(TR)

lib: libcppcms.a

$(TR) : $(OBJ)
$(CXX) -o $@ $^ $(LIBS)

libcppcms.a : $(LOBJ)
ar rvu libcppcms.a $(LOBJ)
ranlib libcppcms.a

.cpp.o:
$(CXX) -c $(CFLAGS) $<

clean:
rm -f $(OBJ) $(TR) .depend

depend:
$(CXX) -I.. -M $(SRC) > .depend

install: $(TR)
/etc/init.d/lighttpd stop
sleep 1
cp $(TR) /home/artik/Projects/www/c/
chown artik:artik /home/artik/Projects/www/c/$(TR)
/etc/init.d/lighttpd start

-include .depend

+ 0
- 3
templates.cpp View File

@@ -75,7 +75,6 @@ int Renderer::render(string &s)
s+=var.gets();
}
else if(debug) {
cerr<<"A"<<op->parameter<<endl;
throw HTTP_Error("Undefined variable");
}
break;
@@ -114,7 +113,6 @@ int Renderer::render(string &s)
}
}
else if(debug){
cerr<<"B"<<op->parameter<<endl;
throw HTTP_Error("Undefined variable");
}
break;
@@ -125,7 +123,6 @@ int Renderer::render(string &s)
}
}
else if(debug){
cerr<<"C"<<op->parameter<<endl;
throw HTTP_Error("Undefined variable");
}
break;


+ 1
- 1
templates.h View File

@@ -8,7 +8,7 @@

#include <sys/mman.h>

#include "compiler/bytecode.h"
#include "share/bytecode.h"
#include "textstream.h"

using namespace std;


+ 3
- 3
tests/bdbtest.cpp View File

@@ -14,7 +14,7 @@ int main(int argc,char **argv)
{
Environment e("./db/");
Index_Auto_Increment<data,int,&data::val> db(e,"test.db",DB_BTREE);
data d;
int i;

@@ -28,9 +28,9 @@ int main(int argc,char **argv)
e.open();
db.open();
}
cursor<data,int> cur(db);
if(argc==2 && argv[1][0]=='c') {
for(i=0;i<N;i++) {
d.val=i;


Loading…
Cancel
Save