我正在做的事情有点棘手。我试图使用
recv
挂钩mongoose的
LD_PRELOAD
函数。在mongoose收到请求后,它首先会将此请求存储到Berkeley DB中,然后继续。
但是,我发现Berkeley DB的存储速度比平常慢得多。存储相同大小的内容,独立程序只需要1000纳秒,但钩住的猫鼬最多可能需要20毫秒。我完全不知道这是怎么发生的。任何帮助将不胜感激。
typedef uint32_t req_id_t;
typedef uint32_t view_id_t;
typedef struct view_stamp_t{
view_id_t view_id;
req_id_t req_id;
}view_stamp;
typedef struct db_t{
DB* bdb_ptr;
}db;
#define BILLION 1000000000L
const char* db_dir="./.db";
uint64_t vstol(view_stamp vs){
uint64_t result = ((uint64_t)vs.req_id)&0xFFFFFFFFl;
uint64_t temp = (uint64_t)vs.view_id&0xFFFFFFFFl;
result += temp<<32;
return result;
};
void mk_path(char* dest,const char* prefix,const char* db_name){
memcpy(dest,prefix,strlen(prefix));
dest[strlen(prefix)] = '/';
memcpy(dest+strlen(prefix)+1,db_name,strlen(db_name));
dest[strlen(prefix)+strlen(db_name)+1] = '\0';
return;
}
db* initialize_db(const char* db_name,uint32_t flag)
{
db* db_ptr=NULL;
DB* b_db;
DB_ENV* dbenv;
int ret;
char* full_path = NULL;
if((ret=mkdir(db_dir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))!=0){
if(errno!=EEXIST){
goto db_init_return;
}
}
full_path = (char*)malloc(strlen(db_dir) + strlen(db_name)+2);
mk_path(full_path,db_dir,db_name);
if ((ret = db_env_create(&dbenv,0)) != 0) {
dbenv->err(dbenv, ret, "Environment Created: %s", db_dir);
goto db_init_return;
}
if ((ret = dbenv->open(dbenv,db_dir,DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 0)) != 0) {
goto db_init_return;
}
/* Initialize the DB handle */
if((ret = db_create(&b_db,dbenv,flag))!=0){
goto db_init_return;
}
if((ret = b_db->open(b_db,NULL,db_name,NULL,DB_BTREE,DB_THREAD|DB_CREATE,0))!=0){
goto db_init_return;
}
db_ptr = (db*)(malloc(sizeof(db)));
db_ptr->bdb_ptr = b_db;
db_init_return:
if(full_path!=NULL){
free(full_path);
}
return db_ptr;
}
int store_record(db* db_p, size_t key_size, void* key_data, size_t data_size, void* data){
int ret = 1;
if((NULL == db_p)||(NULL == db_p->bdb_ptr)){
if(db_p == NULL){
printf("DB store_record : db_p is null.\n");
} else{
printf("DB store_recor : db_p->bdb_ptr is null.\n");
}
goto db_store_return;
}
DB* b_db = db_p->bdb_ptr;
DBT key,db_data;
memset(&key, 0, sizeof(key));
memset(&db_data, 0, sizeof(db_data));
key.data = key_data;
key.size = key_size;
db_data.data = data;
db_data.size = data_size;
struct timespec start, end;
uint64_t diff;
clock_gettime(CLOCK_MONOTONIC, &start);
if ((ret = b_db->put(b_db,NULL,&key,&db_data,0)) == 0){
}
else{
printf("DB : %s.\n", db_strerror(ret));
}
clock_gettime(CLOCK_MONOTONIC, &end);
diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;
printf("elapsed time = %llu nanoseconds\n", (long long unsigned int) diff);
db_store_return:
return ret;
}
int i = 1;
view_stamp vs;
db* db_ptr;
ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
if (i == 1)
{
db_ptr = initialize_db("node_test",0);
vs.view_id = 0;
vs.req_id = 0;
}
i = 0;
typedef ssize_t (*orig_recv_type)(int, void *, size_t, int);
orig_recv_type orig_recv;
orig_recv = (orig_recv_type) dlsym(RTLD_NEXT, "recv");
ssize_t ret = orig_recv(sockfd, buf, len, flags);
vs.req_id++;
uint64_t record_no = vstol(vs);
store_record(db_ptr, sizeof(record_no), &record_no, ret, buf);
return ret;
}