Example #1
0
//批量读取边,返回所有的边,源顶点和目的顶点就没有规律了,还要在上面封装接口来读取某个源顶点和目的顶点的边,也可以由用户完成
//如果vertexes是空,则不会发送请求
uint32_t Client::read_two_edges(list<Two_vertex>& vertexes,list<Edge_u> &edges){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//找所有边的元数据,由于有缓存,这个操作不会成为瓶颈。边在获取元数据的时候按照ip分类
	unordered_map<string,list<Two_vertex>*> classify;
	list<Two_vertex>::iterator it=vertexes.begin();
	unordered_map<string,list<Two_vertex>*>::iterator it_cl;
	string ip;
	while(it!=vertexes.end()){
		ip=get_meta(graph_name,(*it).s_id);
		it_cl=classify.find(ip);
		if(it_cl==classify.end()){
			//如果没有这个ip类,则创建,然后把边加入到该ip类
			classify.insert(pair<string,list<Two_vertex>*>(ip,new list<Two_vertex>()));
			it_cl=classify.find(ip);
			it_cl->second->push_back(*it);	
		}else{
			it_cl->second->push_back(*it);	
		}
		it++;
	}
	//元数据查完后,就开始分别把每个ip类的顶点对发送出去
	it_cl=classify.begin();
	while(it_cl!=classify.end()){	
		Requester req_slave(*find_sock(it_cl->first));
		req_slave.ask(CMD_READ_TWO_EDGES,*(it_cl->second),graph_name);
		req_slave.parse_ans(edges);
		delete it_cl->second;//这个ip类的边插完了,则释放空间
		it_cl++;
	}
	return STATUS_OK;
}
Example #2
0
//多线程批量读取具有某属性的所有边
uint32_t Client::read_edge_index_pthread(string id,list<Edge_u> **edges,uint32_t *size){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
        //获取所有节点的ip
        vector<string> ips;
        get_all_meta(ips);
        //构造参数proto_blog_id,长度超过后,就会截取
        proto_blog_id blog_id(graph_name,id); 
	//多线程的发送,所以要给每个线程数据
	*size=ips.size();
	*edges=new list<Edge_u>[*size];
	Ip_Blog_ID* datas=new Ip_Blog_ID[*size];
	uint32_t index=0;
	pthread_t *threads=new pthread_t[*size];
	for(int index=0;index<*size;index++){
		datas[index].blog_id=blog_id;
		datas[index].sock=find_sock(ips[index]);
		datas[index].edges=&(*edges)[index];
		pthread_create(&threads[index],NULL,thread_read_edge_index,&datas[index]);
	}
	//等待线程的运行完成
	for(index=0;index<*size;index++){
		pthread_join(threads[index],NULL);
	}
	delete[] datas;
	delete[] threads;
	return STATUS_OK;
}
Example #3
0
//多线程查询边数目
uint32_t Client::get_edge_num_pthread(uint32_t **nums,uint32_t *size){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
        //获取所有节点的ip
        vector<string> ips;
        get_all_meta(ips);
	//多线程的发送,所以要给每个线程数据
	*size=ips.size();
	*nums=new uint32_t[*size];
	Ip_Graph* datas=new Ip_Graph[*size];
	uint32_t index=0;
	pthread_t *threads=new pthread_t[*size];
	for(int index=0;index<*size;index++){
		datas[index].graph_name=graph_name;
		datas[index].sock=find_sock(ips[index]);
                datas[index].nums=&(*nums)[index];
		pthread_create(&threads[index],NULL,thread_get_edge_num,&datas[index]);
	}
	//等待线程的运行完成
	for(index=0;index<*size;index++){
		pthread_join(threads[index],NULL);
	}
	delete[] datas;
	delete[] threads;
	return STATUS_OK;
}
Example #4
0
//多线程查询顶点数目
uint32_t Client::read_all_vertex(list<Vertex_u> **vertexes,uint32_t *size){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
    //获取所有节点的ip
    vector<string> ips;
    get_all_meta(ips);
	//多线程的发送,所以要给每个线程数据
	*size=ips.size();
	*vertexes=new list<Vertex_u>[*size];
	Ip_All_Vertex* datas=new Ip_All_Vertex[*size];
	uint32_t index=0;
	pthread_t *threads=new pthread_t[*size];
	for(int index=0;index<*size;index++){
		datas[index].graph_name=graph_name;
		datas[index].sock=find_sock(ips[index]);
        datas[index].vertexes=&(*vertexes)[index];
		pthread_create(&threads[index],NULL,thread_read_all_vertex,&datas[index]);
	}
	//等待线程的运行完成
	for(index=0;index<*size;index++){
		pthread_join(threads[index],NULL);
	}
	delete[] datas;
	delete[] threads;
	return STATUS_OK;
}
Example #5
0
//根据某个属性范围,查询所有的边
uint32_t Client::read_edge_index_range(list<Edge_u> &edges,string min,string max){
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//如果连接图了,则首先找图和顶点的元数据,先在缓存中找,没找到再去master询问
	string ip=string(getenv("LOCAL_IP"));
	Requester req_slave(*find_sock(ip));
	proto_blog_id_range mes_slave(graph_name,min,max);
	req_slave.ask(CMD_GET_INDEX_RANGE_EDGE,&mes_slave,sizeof(proto_blog_id_range));
	req_slave.parse_ans(edges);
    return STATUS_OK;
}
Example #6
0
//返回一个顶点的所有边
uint32_t Client::read_edges(v_type id,list<Edge_u>& edges){
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//如果连接图了,则首先找图和源顶点的元数据,先在缓存中找,没找到再去master询问
	string ip=get_meta(graph_name,id);
	Requester req_slave(*find_sock(ip));
	proto_graph_vertex mes_slave(graph_name,id);
	req_slave.ask(CMD_READ_EDGES,&mes_slave,sizeof(proto_graph_vertex));
	req_slave.parse_ans(edges);
	return req_slave.get_status();
}
Example #7
0
//增加一条边,顶点不存在的时候不会自动创建顶点,添加边就会失败
uint32_t Client::add_edge(Edge_u &e){
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//如果连接图了,则首先找图和源顶点的元数据,先在缓存中找,没找到再去master询问
	string ip=get_meta(graph_name,e.s_id);
	Requester req_slave(*find_sock(ip));
	proto_edge_u mes_slave(graph_name,e);
	req_slave.ask(CMD_ADD_EDGE,&mes_slave,sizeof(proto_edge_u));
	req_slave.parse_ans();
	return req_slave.get_status();//返回结果
}
Example #8
0
//查询出度在某个范围内的顶点
uint32_t Client::read_index_vertex(list<Vertex_u>& vertexes,e_type min,e_type max){
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//如果连接图了,则首先找图和顶点的元数据,先在缓存中找,没找到再去master询问
	string ip=string(getenv("LOCAL_IP"));
	Requester req_slave(*find_sock(ip));
	proto_graph_cd mes_slave(graph_name,min,max);
	req_slave.ask(CMD_GET_INDEX_VERTEX,&mes_slave,sizeof(proto_graph_cd));
	req_slave.parse_ans(vertexes);
    return STATUS_OK;
}
Example #9
0
//增加一个顶点
uint32_t Client::add_vertex(Vertex_u &v){
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//先得到元数据信息,也就是顶点所在ip
	string ip=get_meta(graph_name,v.id);	
	//向slave添加顶点
	Requester req_slave(*find_sock(ip));
	proto_graph_vertex_u mes_slave(graph_name,v);
	req_slave.ask(CMD_ADD_VERTEX,&mes_slave,sizeof(proto_graph_vertex_u));
	req_slave.parse_ans();
	return req_slave.get_status();//返回结果
}
Example #10
0
//多线程版,批量增加边,如果num不为空,则存储实际添加的边的数目,因为有些顶点可能不存在,添加就会失败
uint32_t Client::add_edges_pthread(list<Edge_u> &edges,uint32_t *num){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//找所有边的元数据,由于有缓存,这个操作不会成为瓶颈。边在获取元数据的时候按照ip分类
	unordered_map<string,list<Edge_u>*> classify;
	list<Edge_u>::iterator it=edges.begin();
	unordered_map<string,list<Edge_u>*>::iterator it_cl;
	string ip;
	while(it!=edges.end()){
		ip=get_meta(graph_name,(*it).s_id);
		it_cl=classify.find(ip);
		if(it_cl==classify.end()){
			//如果没有这个ip类,则创建,然后把边加入到该ip类
			classify.insert(pair<string,list<Edge_u>*>(ip,new list<Edge_u>()));
			it_cl=classify.find(ip);
			it_cl->second->push_back(*it);	
		}else{
			it_cl->second->push_back(*it);	
		}
		it++;
	}
	//元数据查完后,就开始分别把每个ip类的边发送出去
	uint32_t size=classify.size();
	Ip_Edges* datas=new Ip_Edges[size];
	uint32_t index=0;
	pthread_t *threads=new pthread_t[size];
	it_cl=classify.begin();
	while(it_cl!=classify.end()){
		datas[index].graph_name=graph_name;
		datas[index].sock=find_sock(it_cl->first);
		datas[index].edges=it_cl->second;
		datas[index].num=0;
		pthread_create(&threads[index],NULL,thread_add_edges,&datas[index]);	
		index++;	
		it_cl++;
	}
	//等待线程的运行完成
	for(index=0;index<size;index++){
		pthread_join(threads[index],NULL);
	}
	//计算成功添加的边数
	if(num!=NULL){
		*num=0;
		for(index=0;index<size;index++){
			*num+=datas[index].num;
		}
	}
	//清理内存
	for(index=0;index<size;index++){
		delete datas[index].edges;
	}
	delete[] datas;
	delete[] threads;
	return STATUS_OK;
}
Example #11
0
//多线程批量读取边
uint32_t Client::read_two_edges_pthread(list<Two_vertex>& vertexes,list<Edge_u> **edges,uint32_t *size){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//找所有边的元数据,由于有缓存,这个操作不会成为瓶颈。边在获取元数据的时候按照ip分类
	unordered_map<string,list<Two_vertex>*> classify;
	list<Two_vertex>::iterator it=vertexes.begin();
	unordered_map<string,list<Two_vertex>*>::iterator it_cl;
	string ip;
	while(it!=vertexes.end()){
		ip=get_meta(graph_name,(*it).s_id);
		it_cl=classify.find(ip);
		if(it_cl==classify.end()){
			//如果没有这个ip类,则创建,然后把边加入到该ip类
			classify.insert(pair<string,list<Two_vertex>*>(ip,new list<Two_vertex>()));
			it_cl=classify.find(ip);
			it_cl->second->push_back(*it);	
		}else{
			it_cl->second->push_back(*it);	
		}
		it++;
	}
	//元数据查完后,就开始分别把每个ip类的顶点对发送出去,多线程的发送,所以要给每个线程数据
	*size=classify.size();
	*edges=new list<Edge_u>[*size];
	Ip_Two_Vertex* datas=new Ip_Two_Vertex[*size];
	uint32_t index=0;
	pthread_t *threads=new pthread_t[*size];
	it_cl=classify.begin();
	while(it_cl!=classify.end()){
		datas[index].graph_name=graph_name;
		datas[index].sock=find_sock(it_cl->first);
		datas[index].vertexes=it_cl->second;
		datas[index].edges=&(*edges)[index];
		pthread_create(&threads[index],NULL,thread_read_two_edges,&datas[index]);	
		index++;	
		it_cl++;
	}
	//等待线程的运行完成
	for(index=0;index<*size;index++){
		pthread_join(threads[index],NULL);
	}
	//清理内存
	for(index=0;index<*size;index++){
		delete datas[index].vertexes;
	}
	delete[] datas;
	delete[] threads;
	return STATUS_OK;
}
Example #12
0
//查询顶点的信息,如果顶点存在则返回ok状态,不存在返回
uint32_t Client::read_vertex(v_type id,Vertex_u& v,uint32_t *num){
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//如果连接图了,则首先找图和顶点的元数据,先在缓存中找,没找到再去master询问
	string ip=get_meta(graph_name,id);
	Requester req_slave(*find_sock(ip));
	proto_graph_vertex mes_slave(graph_name,id);
	req_slave.ask(CMD_READ_VERTEX,&mes_slave,sizeof(proto_graph_vertex));
	req_slave.parse_ans();
        uint32_t res=req_slave.get_status();
        if(res==STATUS_OK){
	    proto_vertex_num *mes=(proto_vertex_num*)req_slave.get_data(); 
            v=mes->vertex;
            *num=mes->num; 
        }
        return res;
}
Example #13
0
//批量增加边,如果num不为空,则存储实际添加的边的数目,因为有些顶点可能不存在,添加就会失败
uint32_t Client::add_edges(list<Edge_u> &edges,uint32_t *num){	
	if(current_graph()=="") return STATUS_NOT_EXIST;//如果还没有连接图,则返回状态STATUS_NOT_EXIST
	//找所有边的元数据,由于有缓存,这个操作不会成为瓶颈。边在获取元数据的时候按照ip分类
	unordered_map<string,list<Edge_u>*> classify;
	list<Edge_u>::iterator it=edges.begin();
	unordered_map<string,list<Edge_u>*>::iterator it_cl;
	string ip;
	while(it!=edges.end()){
		ip=get_meta(graph_name,(*it).s_id);
		it_cl=classify.find(ip);
		if(it_cl==classify.end()){
			//如果没有这个ip类,则创建,然后把边加入到该ip类
			classify.insert(pair<string,list<Edge_u>*>(ip,new list<Edge_u>()));
			it_cl=classify.find(ip);
			it_cl->second->push_back(*it);	
		}else{
			it_cl->second->push_back(*it);	
		}
		it++;
	}
	//元数据查完后,就开始分别把每个ip类的边发送出去
	if(num!=NULL) *num=0;
	it_cl=classify.begin();
	while(it_cl!=classify.end()){	
		Requester req_slave(*find_sock(it_cl->first));
		req_slave.ask(CMD_ADD_EDGES,*(it_cl->second),graph_name);
		req_slave.parse_ans();
		if(num!=NULL){
			//统计插入的边的数目
			*num+=atoi((char*)req_slave.get_data());
		}
		delete it_cl->second;//这个ip类的边插完了,则释放空间
		it_cl++;
	}
	return STATUS_OK;
}
Example #14
0
int start_room(int sock, map<string, string> param, list<int> &send_sock_list, char *buf)
{
    char c_rst[10];
    int result = START_ROOM_SUCCESS;
    send_sock_list.push_back(sock);
    do
    {
        // param sid not exist
        if (param.count("sid") == 0)
        {
            result = PARAM_ERROR;
            LOG_ERROR << "param sid not exist" << endl;
            break;
        }

        // session is not exist
        SESSION *s = Session::get(Tool::trim(param["sid"]));
        if (s == NULL) {
            result = SESSION_NOT_EXIST;
            LOG_ERROR << "session not exist" << endl;
            break;
        }
        int user_id = Tool::S2I(s->uid);
        LOG_INFO << "user id :" << user_id << endl;

        int room_id = Tool::S2I(param["roomId"]);

        if (room_id < 0)
        {
            result = PARAM_ERROR;
            LOG_ERROR << "room id error :" << room_id << endl;
            break;
        }

        // database params
        Config *c = Config::get_instance();
        map<string, string> config = c->get_config();
        eagleMysql e(config["DOMAIN"].c_str(), config["USER_NAME"].c_str(), config["PASSWORD"].c_str(), config["DATABASE"].c_str(), Tool::S2I(config["PORT"], 3306));

        bool is_exist_room;
        // whether room exist
        e.is_exist("t_room",  "where id = " + Tool::mysql_filter(room_id) + " and room_status = 0", is_exist_room);
        if (!is_exist_room)
        {
            result = START_ROOM_HASSTARTED_OR_NOTEXIST;
            LOG_ERROR << "room has started or not exist" << endl;
            break;
        }

        // connect fail
        if (!e.connet()) {
            result = DB_ERROR;
            LOG_ERROR << "connect fail" << endl; 
            e.close();
            break;
        }

        string sql = "SELECT r.owner_id, rel.user_id FROM t_room r left join t_room_user_relation rel "
        " on r.id = rel.room_id where r.id = " + Tool::mysql_filter(room_id);


        result = e.excute(sql);
        // exception
        if (result != DB_OK) {
            LOG_ERROR << "DB ERROR|get owner and joined people|" + Tool::toString(result) << endl;
            result = DB_ERROR;
            e.close();
            break;
        }

        MYSQL mysql = e.get_mysql();

        MYSQL_RES *rst = NULL;
        MYSQL_FIELD *field = NULL;
        MYSQL_ROW row = NULL;


        rst = mysql_store_result(&mysql);
        int fieldcount = mysql_num_fields(rst);
        row = mysql_fetch_row(rst);

        int owner_id = -1;
        vector<int> join_peo_list;
        while(NULL != row) 
        {
            for(int i = 0; i < fieldcount; i++) 
            {
                field = mysql_fetch_field_direct(rst, i);
                string key = field->name;
                if (row[i] == NULL)
                    continue;
                // LOG_DEBUG << row[i] << endl;
                if (key == "owner_id") {
                    owner_id = Tool::S2I(row[i]);
                } else if (key == "user_id") {
                    int join_peo_id = Tool::S2I(row[i]);
                    if (join_peo_id > 0)
                        join_peo_list.push_back(join_peo_id);
                }
            }
            row = mysql_fetch_row(rst);
        }
        e.close();


        // judge whether owner
        LOG_DEBUG << "owner_id:" << owner_id << endl;
        if (owner_id != user_id) {
            result = START_ROOM_ISNOT_OWNER;
            LOG_ERROR << "user is not owner" << endl;
            break;
        }

        // update room status
        if (!e.connet()) {
            result = DB_ERROR;
            LOG_ERROR << "connect fail" << endl; 
            e.close();
            break;
        }
        string update_room_sql = "update t_room set room_status = 1 "
        " and begin_time = " + Tool::now_time() +
        " where id = " + Tool::mysql_filter(room_id);

        result = e.excute(update_room_sql);
        // exception
        if (result != DB_OK) {
            LOG_ERROR << "DB ERROR|update t_room|" + Tool::toString(result) << endl;
            result = DB_ERROR;
            e.close();
            break;
        }

        // update success, add join_peo to sock list
        for (int i = 0; i < (int) join_peo_list.size(); i++)
        {
            LOG_DEBUG << "join peo id:" << join_peo_list[i] << endl;
            if (join_peo_list[i] > 0 && join_peo_list[i] != user_id) {
                int so = find_sock(join_peo_list[i]);
                if (!(so < 0 || so == sock))
                    send_sock_list.push_back(so);
            }
        }
        result = START_ROOM_SUCCESS;
    } while(0);
    sprintf(c_rst, "%d", result);
    strncpy(buf, c_rst, strlen(c_rst) + 1);
    return result;
}
Example #15
0
int save_msg(int sock, map<string, string> param, list<int> &send_sock_list, char *buf)
{
    char c_rst[10];
    int result;
    send_sock_list.push_back(sock);
    do
    {
        // sid?

        int sender_id = Tool::S2I(param["senderId"]);
        int recipient_id = Tool::S2I(param["recipientId"]);
        int room_id = Tool::S2I(param["roomId"]);
        int msg_type = Tool::S2I(param["msgType"]);
        string content = param["content"];

        if (sender_id < 0 || !(msg_type == 1 || msg_type == 2) || Tool::trim(content).empty())
        {
            result = PARAM_ERROR;
            LOG_ERROR << "param error" << endl;
            break;
        }

        // database params
        Config *c = Config::get_instance();
        map<string, string> config = c->get_config();
        eagleMysql e(config["DOMAIN"].c_str(), config["USER_NAME"].c_str(), config["PASSWORD"].c_str(), config["DATABASE"].c_str(), Tool::S2I(config["PORT"], 3306));

        // connect fail
        if (!e.connet()) {
            result = DB_ERROR;
            LOG_ERROR << "connect fail" << endl; 
            e.close();
            break;
        }

        MYSQL mysql;
        int db_ret;
        mysql = e.get_mysql();

        string call_pr = "call pr_insert_msg (" + Tool::toString(sender_id) + ", " 
            + Tool::toString(recipient_id) + ", " + Tool::toString(room_id) + ", " 
            + Tool::toString(msg_type) + ", " + Tool::mysql_filter(content) +", @ret, @send_user_list)";
        LOG_DEBUG << call_pr << endl;
        db_ret = mysql_query(&mysql, call_pr.c_str());
        db_ret = mysql_query(&mysql, "SELECT @ret, @send_user_list");

        // exception
        if (db_ret)
        {
            result = DB_ERROR;
            e.close();
            LOG_ERROR << "DB ERROR|" << db_ret << endl; 
            break;
        }
        MYSQL_RES *db_rst = NULL;
        db_rst = mysql_store_result(&mysql);
        MYSQL_ROW row = NULL;
        row = mysql_fetch_row(db_rst);

        db_ret = Tool::S2I(row[0]);
        string send_list = row[1];

        LOG_DEBUG << "db_ret:" << db_ret << "|send_list:" << send_list << endl;

        if (db_ret == DB_PR_ERR)
        {
            result = DB_ERROR;
            LOG_ERROR << "call pr_insert_msg err|" << endl;
            e.close();
            break;
        }
        if (db_ret == DB_PR_INSERT_MSG_SENDER_NOTEXIST)
        {
            result = SAVE_MSG_SENDER_NOTEXIST;
            LOG_ERROR << "sender not exist" << endl;
            e.close();
            break;
        }
        if (db_ret == DB_PR_INSERT_MSG_ROOM_NOTEXIST)
        {
            result = SAVE_MSG_ROOM_NOTEXIST;
            LOG_ERROR << "room not exist" << endl;
            e.close();
            break;
        }
        if (db_ret == DB_PR_INSERT_MSG_RECIPIENT_NOTEXIST)
        {
            result = SAVE_MSG_RECIPIENT_NOTEXIST;
            LOG_ERROR << "recipient not exist" << endl;
            e.close();
            break;
        }
        if (db_ret == DB_PR_INSERT_MSG_MSGTYPE_ERROR)
        {
            result = SAVE_MSG_MSGTYPE_ERROR;
            LOG_ERROR << "msg type error" << endl;
            e.close();
            break;
        }
        if (msg_type == 1) {
            result = SAVE_MSG_GROUP_SUCCESS;
        } else {
            result = SAVE_MSG_SINGLE_SUCCESS;
        }
        std::vector<string> v = Tool::split(send_list, "|");
        for (int i = 0; i < (int)v.size(); i++)
        {
            int so = find_sock(Tool::S2I(v[i]));
            LOG_DEBUG << v[i] << "|" << so << endl;
            if (!(so < 0 || so == sock))
                send_sock_list.push_back(so);
        }


    } while(0);
    sprintf(c_rst, "%d", result);
    strncpy(buf, c_rst, strlen(c_rst) + 1);
    return result;
}
Example #16
0
int quit_room(int sock, map<string, string> param, list<int> &send_sock_list, char *buf)
{
    char c_rst[10];
    int result;
    send_sock_list.push_back(sock);
    do
    {
        // param sid not exist
        if (param.count("sid") == 0)
        {
            result = PARAM_ERROR;
            LOG_ERROR << "param sid not exist" << endl;
            break;
        }

        // session is not exist
        SESSION *s = Session::get(Tool::trim(param["sid"]));
        if (s == NULL) {
            result = SESSION_NOT_EXIST;
            LOG_ERROR << "session not exist" << endl;
            break;
        }
        int user_id = Tool::S2I(s->uid);
        LOG_INFO << "user id :" << user_id << endl;

        int room_id = Tool::S2I(param["roomId"]); 
        if (room_id < 0)
        {
            result = PARAM_ERROR;
            LOG_ERROR << "room_id error" << endl;
            break;
        }

        // database params
        Config *c = Config::get_instance();
        map<string, string> config = c->get_config();
        eagleMysql e(config["DOMAIN"].c_str(), config["USER_NAME"].c_str(), config["PASSWORD"].c_str(), config["DATABASE"].c_str(), Tool::S2I(config["PORT"], 3306));

        // connect fail
        if (!e.connet()) {
            result = DB_ERROR;
            LOG_ERROR << "connect fail" << endl; 
            e.close();
            break;
        }

        MYSQL mysql;
        int db_ret;
        mysql = e.get_mysql();

        string call_pr = "call pr_quit_room(" + 
            Tool::toString(room_id) + ", " + Tool::toString(user_id) +
            " , @ret, @now_room_peo_list)";
        LOG_INFO << call_pr << endl;
        db_ret = mysql_query(&mysql, call_pr.c_str());
        db_ret = mysql_query(&mysql, "SELECT @ret, @now_room_peo_list");

        // exception
        if (db_ret)
        {
            result = DB_ERROR;
            LOG_ERROR << "DB ERROR|quit room call pr" << endl;
            e.close();
            break;
        }

        MYSQL_RES *db_rst = NULL;
        db_rst = mysql_store_result(&mysql);
        MYSQL_ROW row = NULL;
        row = mysql_fetch_row(db_rst);

        db_ret = Tool::S2I(row[0]);
        if (db_ret != DB_PR_QUIT_ROOM_SUCCESS)
        {
            result = DB_ERROR;
            LOG_ERROR << "call pr_quit_room result:" << db_ret << endl;
            e.close();
            break;
        }

        // find all people in room
        LOG_INFO << "room people list:" << row[1] << endl;
        vector<string> v_room_peo = Tool::split(row[1], "|");
        for (int i = 0; i < v_room_peo.size(); i++)
        {
            int uid = Tool::S2I(v_room_peo[i]);
            if (uid < 0 || uid == user_id)
                continue;
            int so = find_sock(uid);
            LOG_INFO << "send sock|" << uid << "|" << so << endl;
            if (!(so < 0 || so == sock))
                send_sock_list.push_back(so);
        }
        result = LC_QUIT_ROOM_SUCCESS;

    } while(0);
    sprintf(c_rst, "%d", result);
    strncpy(buf, c_rst, strlen(c_rst) + 1);
    return result;
}