//批量读取边,返回所有的边,源顶点和目的顶点就没有规律了,还要在上面封装接口来读取某个源顶点和目的顶点的边,也可以由用户完成 //如果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; }
//多线程批量读取具有某属性的所有边 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; }
//多线程查询边数目 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; }
//多线程查询顶点数目 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; }
//根据某个属性范围,查询所有的边 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; }
//返回一个顶点的所有边 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(); }
//增加一条边,顶点不存在的时候不会自动创建顶点,添加边就会失败 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();//返回结果 }
//查询出度在某个范围内的顶点 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; }
//增加一个顶点 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();//返回结果 }
//多线程版,批量增加边,如果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; }
//多线程批量读取边 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; }
//查询顶点的信息,如果顶点存在则返回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; }
//批量增加边,如果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; }
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; }
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; }
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; }