diff options
Diffstat (limited to 'toj/judge/center_manage.cpp')
-rw-r--r-- | toj/judge/center_manage.cpp | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/toj/judge/center_manage.cpp b/toj/judge/center_manage.cpp new file mode 100644 index 0000000..f994bd9 --- /dev/null +++ b/toj/judge/center_manage.cpp @@ -0,0 +1,615 @@ +#include<stdio.h> +#include<stdlib.h> +#include<string.h> +#include<limits.h> +#include<dlfcn.h> +#include<unistd.h> +#include<pthread.h> +#include<semaphore.h> +#include<libpq-fe.h> +#include<sys/eventfd.h> +#include<sys/stat.h> +#include<json/json.h> +#include<vector> +#include<queue> +#include<map> +#include<string> + +#include"tpool.h" +#include"event_exec.h" +#include"judge_def.h" +#include"judgm_manage.h" +#include"center.h" +#include"center_manage.h" + +int center_manage_init(tpool **tpinfo){ + manage_tp = new tpool(4); + manage_tp->start(); + *tpinfo = manage_tp; + + manage_updatepro_thfn = new tpool_static_fn(manage_updatepro_th); + manage_updatepro_cbfn = new tpool_static_fn(manage_updatepro_cb); + manage_updatejmod_thfn = new tpool_static_fn(manage_updatejmod_th); + manage_updatejmod_cbfn = new tpool_static_fn(manage_updatejmod_cb); + manage_submit_thfn = new tpool_static_fn(manage_submit_th); + manage_submit_cbfn = new tpool_static_fn(manage_submit_cb); + + //run when startup + center_manage_updatedata(); + center_manage_submitwait(); + return 0; +} +PGconn* center_manage_conndb(){ + return PQconnectdb("host=localhost port=5432 dbname=xxxxx user=xxxxx password=xxxxx"); +} +int center_manage_closedb(PGconn *conn){ + PQfinish(conn); + return 0; +} +int center_manage_updatedata(){ + int i; + + PGconn *db_conn; + PGresult *db_res; + int db_count; + int cacheid; + center_jmod_info *jmod_info; + int proid; + int lang_flag; + std::map<std::string,center_jmod_info*>::iterator jmod_it; + center_pro_info *pro_info; + + std::vector<std::pair<int,int> > pro_list; + + if((db_conn = center_manage_conndb()) == NULL){ + return -1; + } + + db_res = PQexec(db_conn,"SELECT DISTINCT \"jmodname\" FROM \"mod\";"); + if(PQresultStatus(db_res) != PGRES_TUPLES_OK){ + center_manage_closedb(db_conn); + return -1; + } + + db_count = PQntuples(db_res); + for(i = 0;i < db_count;i++){ + jmod_info = new center_jmod_info(PQgetvalue(db_res,i,0),2); + center_manage_jmodmap.insert(std::pair<std::string,center_jmod_info*>(jmod_info->name,jmod_info)); + } + PQclear(db_res); + + db_res = PQexec(db_conn,"SELECT \"proid\",\"cacheid\",\"lang\",\"jmodname\" FROM \"problem\" INNER JOIN \"mod\" ON (\"problem\".\"modid\"=\"mod\".\"modid\");"); + if(PQresultStatus(db_res) != PGRES_TUPLES_OK){ + center_manage_closedb(db_conn); + return -1; + } + + db_count = PQntuples(db_res); + for(i = 0;i < db_count;i++){ + sscanf(PQgetvalue(db_res,i,0),"%d",&proid); + sscanf(PQgetvalue(db_res,i,1),"%d",&cacheid); + sscanf(PQgetvalue(db_res,i,2),"%d",&lang_flag); + if((jmod_it = center_manage_jmodmap.find(PQgetvalue(db_res,i,3))) == center_manage_jmodmap.end()){ + continue; + } + + if(manage_updatepro(proid,cacheid,jmod_it->second,lang_flag) == 1){ + pro_list.push_back(std::make_pair(proid,cacheid)); + + printf("pro update %d %d\n",proid,cacheid); + } + } + PQclear(db_res); + + if(!pro_list.empty()){ + center_judge_updatepro(pro_list); + } + + center_manage_closedb(db_conn); + return 0; +} +int center_manage_submitwait(){ + int i; + + PGconn *db_conn; + PGresult *db_res; + int db_count; + int subid; + + if((db_conn = center_manage_conndb()) == NULL){ + return -1; + } + + db_res = PQexec(db_conn,"SELECT \"subid\" FROM \"submit\" WHERE \"result\"=100;"); + if(PQresultStatus(db_res) != PGRES_TUPLES_OK){ + center_manage_closedb(db_conn); + return -1; + } + + db_count = PQntuples(db_res); + for(i = 0;i < db_count;i++){ + sscanf(PQgetvalue(db_res,i,0),"%d",&subid); + center_manage_submit(subid,"{}"); + } + + PQclear(db_res); + center_manage_closedb(db_conn); + return 0; +} + + +int center_manage_submit(int subid,char *param){ + PGconn *db_conn; + PGresult *db_res; + char *db_param[1]; + char db_subid[64]; + + int uid; + int proid; + int lang; + int result; + bool rejudge_flag; + std::map<int,center_pro_info*>::iterator pro_it; + center_pro_info *pro_info; + center_jmod_info *jmod_info; + manage_submit_info *sub_info; + + if((db_conn = center_manage_conndb()) == NULL){ + return -1; + } + + snprintf(db_subid,sizeof(db_subid),"%d",subid); + db_param[0] = db_subid; + db_res = PQexecParams(db_conn, + "SELECT \"uid\",\"proid\",\"lang\",\"result\" FROM \"submit\" WHERE \"subid\"=$1;", + 1, + NULL, + db_param, + NULL, + NULL, + 0); + if(PQresultStatus(db_res) != PGRES_TUPLES_OK){ + center_manage_closedb(db_conn); + return -1; + } + + sscanf(PQgetvalue(db_res,0,0),"%d",&uid); + sscanf(PQgetvalue(db_res,0,1),"%d",&proid); + sscanf(PQgetvalue(db_res,0,2),"%d",&lang); + sscanf(PQgetvalue(db_res,0,3),"%d",&result); + PQclear(db_res); + center_manage_closedb(db_conn); + + if((pro_it = center_manage_promap.find(proid)) == center_manage_promap.end()){ + return -1; + } + pro_info = pro_it->second; + + if((lang & pro_info->lang_flag) == 0){ + return -1; + } + jmod_info = pro_info->jmod_info; + + if(result == JUDGE_WAIT){ + rejudge_flag = false; + }else{ + rejudge_flag = true; + } + + center_manage_getpro(pro_info); + + sub_info = new manage_submit_info(subid,uid,jmod_info,pro_info,lang,rejudge_flag,param); + manage_submap.insert(std::pair<int,manage_submit_info*>(sub_info->subid,sub_info)); + manage_tp->add(manage_submit_thfn,sub_info,manage_submit_cbfn,sub_info); + + return 0; +} +static void manage_submit_th(void *data){ + manage_submit_info *sub_info; + char dir_path[PATH_MAX + 1]; + char pack_path[PATH_MAX + 1]; + + sub_info = (manage_submit_info*)data; + + snprintf(dir_path,sizeof(dir_path),"submit/%d/%d/data",(sub_info->subid / 1000) * 1000,sub_info->subid); + snprintf(pack_path,sizeof(pack_path),"tmp/codepack/%d.tar.bz2",sub_info->subid); + tool_pack(pack_path,dir_path); +} +static void manage_submit_cb(void *data){ + manage_submit_info *sub_info; + center_jmod_info *jmod_info; + center_pro_info *pro_info; + + char cwd_path[PATH_MAX + 1]; + char tpath[PATH_MAX + 1]; + judgm_manage_info *mg_info; + judgm_manage_submit_fn mg_sub_fn; + FILE *set_file; + char lchr; + char tchr; + + sub_info = (manage_submit_info*)data; + jmod_info = sub_info->jmod_info; + pro_info = sub_info->pro_info; + + if(jmod_info->manage_dll == NULL){ + getcwd(cwd_path,sizeof(cwd_path)); + snprintf(tpath,sizeof(tpath),"%s/jmod/%s/%s_manage.so",cwd_path,jmod_info->name,jmod_info->name); + + jmod_info->manage_dll = dlopen(tpath,RTLD_NOW); + jmod_info->manage_sub_fn = dlsym(jmod_info->manage_dll,"submit"); + jmod_info->manage_res_fn = dlsym(jmod_info->manage_dll,"result"); + } + mg_sub_fn = (judgm_manage_submit_fn)jmod_info->manage_sub_fn; + + mg_info = sub_info->manage_info; + snprintf(mg_info->pro_path,sizeof(mg_info->pro_path),"pro/%d",pro_info->proid); + snprintf(mg_info->res_path,sizeof(mg_info->res_path),"submit/%d/%d/result",(sub_info->subid / 1000) * 1000,sub_info->subid); + + snprintf(tpath,sizeof(tpath),"pro/%d/setting",pro_info->proid); + set_file = fopen(tpath,"r"); + lchr = '\n'; + while((tchr = fgetc(set_file)) != EOF){ + if(lchr == '\n' && tchr == '='){ + while(fgetc(set_file) != '\n'); + break; + } + lchr = tchr; + } + + mg_sub_fn(mg_info,set_file); + + fclose(set_file); +} +DLL_PUBLIC int center_manage_queuesubmit(int subid,int proid,int lang,char *set_data,size_t set_len){ + center_judge_submit(subid,proid,lang,set_data,set_len); + return 0; +} + +int center_manage_result(int subid,char *res_data){ + std::map<int,manage_submit_info*>::iterator sub_it; + manage_submit_info *sub_info; + center_jmod_info *jmod_info; + + char res_path[PATH_MAX + 1]; + judgm_manage_info *mg_info; + judgm_manage_result_fn mg_res_fn; + + PGconn *db_conn; + PGresult *db_res; + char db_result[32]; + char db_score[32]; + char db_runtime[32]; + char db_memory[32]; + char db_subid[32]; + char *db_param[5]; + + if((sub_it = manage_submap.find(subid)) == manage_submap.end()){ + return -1; + } + sub_info = sub_it->second; + jmod_info = sub_info->jmod_info; + mg_info = sub_info->manage_info; + + mg_res_fn = (judgm_manage_result_fn)jmod_info->manage_res_fn; + if(mg_res_fn(mg_info,res_data)){ + manage_submap.erase(sub_it); + + if((db_conn = center_manage_conndb()) == NULL){ + return -1; + } + + snprintf(db_result,sizeof(db_result),"%d",mg_info->result); + snprintf(db_score,sizeof(db_score),"%lf",mg_info->score); + snprintf(db_runtime,sizeof(db_runtime),"%lu",mg_info->runtime); + snprintf(db_memory,sizeof(db_memory),"%lu",mg_info->memory / 1024UL); + snprintf(db_subid,sizeof(db_subid),"%d",subid); + db_param[0] = db_result; + db_param[1] = db_score; + db_param[2] = db_runtime; + db_param[3] = db_memory; + db_param[4] = db_subid; + db_res = PQexecParams(db_conn, + "UPDATE \"submit\" SET \"result\"=$1,\"score\"=$2,\"runtime\"=$3,\"memory\"=$4 WHERE \"subid\"=$5;", + 5, + NULL, + db_param, + NULL, + NULL, + 0); + PQclear(db_res); + center_manage_closedb(db_conn); + + manage_notice(subid, + sub_info->uid, + sub_info->pro_info->proid, + mg_info->result, + mg_info->score, + mg_info->runtime, + mg_info->memory, + sub_info->rejudge_flag); + + center_manage_putpro(sub_info->pro_info); + delete sub_info; + }else{ + return -1; + } + + return 0; +} +static int manage_notice(int subid,int uid,int proid,int result,double score,int runtime,int memory,bool rejudge_flag){ + char msg[4096]; + json_object *jso_msg; + json_object *jso_arg; + + jso_msg = json_object_new_object(); + json_object_object_add(jso_msg,"type",json_object_new_string("result")); + json_object_object_add(jso_msg,"subid",json_object_new_int(subid)); + json_object_object_add(jso_msg,"proid",json_object_new_int(proid)); + json_object_object_add(jso_msg,"result",json_object_new_int(result)); + json_object_object_add(jso_msg,"score",json_object_new_double(score)); + json_object_object_add(jso_msg,"runtime",json_object_new_int(runtime)); + json_object_object_add(jso_msg,"memory",json_object_new_int(memory / 1024UL)); + json_object_object_add(jso_msg,"rejudge_flag",json_object_new_boolean(rejudge_flag)); + + jso_arg = json_object_new_array(); + json_object_array_add(jso_arg,json_object_new_int(uid)); + json_object_array_add(jso_arg,jso_msg); + + event_exec("pzreadtest.php","center_result_event",json_object_get_string(jso_arg)); + json_object_put(jso_arg); + + return 0; +} + + +center_pro_info* center_manage_getprobyid(int proid){ + std::map<int,center_pro_info*>::iterator pro_it; + center_pro_info *pro_info; + + if((pro_it = center_manage_promap.find(proid)) == center_manage_promap.end()){ + return NULL; + } + pro_info = pro_it->second; + + if(center_manage_getpro(pro_info)){ + return NULL; + } + + return pro_info; +} +int center_manage_getpro(center_pro_info *pro_info){ + pro_info->ref_count++; + return 0; +} +int center_manage_putpro(center_pro_info *pro_info){ + char tpath[PATH_MAX + 1]; + + pro_info->ref_count--; + if(pro_info->ref_count == 0){ + snprintf(tpath,sizeof(tpath),"tmp/pro/%d_%d",pro_info->proid,pro_info->cacheid); + tool_cleardir(tpath); + rmdir(tpath); + + snprintf(tpath,sizeof(tpath),"tmp/propack/%d_%d.tar.bz2",pro_info->proid,pro_info->cacheid); + unlink(tpath); + + delete pro_info; + } + return 0; +} +static int manage_updatepro(int proid,int cacheid,center_jmod_info *jmod_info,int lang_flag){ + std::map<int,center_pro_info*>::iterator pro_it; + center_pro_info *old_pro_info; + center_pro_info *update_pro_info; + + char tpath[PATH_MAX + 1]; + struct stat st; + std::pair<std::map<int,center_pro_info*>::iterator,bool> ins_ret; + + if((pro_it = center_manage_promap.find(proid)) == center_manage_promap.end()){ + old_pro_info = NULL; + }else{ + old_pro_info = pro_it->second; + + if(old_pro_info->state == CENTER_CACHESTATE_READY && cacheid == old_pro_info->cacheid){ + return 1; + } + if(old_pro_info->state == CENTER_CACHESTATE_UPDATE && (cacheid <= old_pro_info->cacheid || cacheid <= old_pro_info->update_cacheid)){ + return -1; + } + + old_pro_info->state = CENTER_CACHESTATE_UPDATE; + old_pro_info->update_cacheid = cacheid; + } + + update_pro_info = new center_pro_info(proid,cacheid,jmod_info,lang_flag); //set cacheid 0 to new pro + center_manage_getpro(update_pro_info); + + snprintf(tpath,sizeof(tpath),"tmp/pro/%d_%d",update_pro_info->proid,update_pro_info->cacheid); + if(!stat(tpath,&st)){ + snprintf(tpath,sizeof(tpath),"tmp/propack/%d_%d.tar.bz2",update_pro_info->proid,update_pro_info->cacheid); + if(!stat(tpath,&st)){ + + if(old_pro_info != NULL){ + center_manage_putpro(old_pro_info); + } + + ins_ret = center_manage_promap.insert(std::make_pair(update_pro_info->proid,update_pro_info)); + if(ins_ret.second == false){ + ins_ret.first->second = update_pro_info; + } + + return 1; + } + } + + manage_tp->add(manage_updatepro_thfn,update_pro_info,manage_updatepro_cbfn,update_pro_info); + + return 0; +} +static void manage_updatepro_th(void *data){ + center_pro_info *pro_info; + char src_path[PATH_MAX + 1]; + char dir_path[PATH_MAX + 1]; + char pack_path[PATH_MAX + 1]; + + pro_info = (center_pro_info*)data; + + snprintf(src_path,sizeof(src_path),"pro/%d",pro_info->proid); + snprintf(dir_path,sizeof(dir_path),"tmp/pro/%d_%d",pro_info->proid,pro_info->cacheid); + tool_copydir(src_path,dir_path); + + snprintf(pack_path,sizeof(pack_path),"tmp/propack/%d_%d.tar.bz2",pro_info->proid,pro_info->cacheid); + tool_pack(pack_path,dir_path); +} +static void manage_updatepro_cb(void *data){ + center_pro_info *old_pro_info; + center_pro_info *update_pro_info; + std::pair<std::map<int,center_pro_info*>::iterator,bool> ins_ret; + std::vector<std::pair<int,int> > pro_pair; + + update_pro_info = (center_pro_info*)data; + + ins_ret = center_manage_promap.insert(std::make_pair(update_pro_info->proid,update_pro_info)); + if(ins_ret.second == false){ + old_pro_info = ins_ret.first->second; + + if(update_pro_info->cacheid <= old_pro_info->cacheid){ + center_manage_putpro(update_pro_info); + return; + } + + center_manage_putpro(ins_ret.first->second); + ins_ret.first->second = update_pro_info; + } + + pro_pair.push_back(std::make_pair(update_pro_info->proid,update_pro_info->cacheid)); + center_judge_updatepro(pro_pair); +} + +center_jmod_info* center_manage_getjmodbyname(char *name){ + std::map<std::string,center_jmod_info*>::iterator jmod_it; + center_jmod_info *jmod_info; + + if((jmod_it = center_manage_jmodmap.find(name)) == center_manage_jmodmap.end()){ + return NULL; + } + jmod_info = jmod_it->second; + + if(center_manage_getjmod(jmod_info)){ + return NULL; + } + + return jmod_info; +} +int center_manage_getjmod(center_jmod_info *jmod_info){ + jmod_info->ref_count++; + return 0; +} +int center_manage_putjmod(center_jmod_info *jmod_info){ + char tpath[PATH_MAX + 1]; + + jmod_info->ref_count--; + if(jmod_info->ref_count == 0){ + snprintf(tpath,sizeof(tpath),"tmp/jmod/%s_%d",jmod_info->name,jmod_info->cacheid); + tool_cleardir(tpath); + rmdir(tpath); + + snprintf(tpath,sizeof(tpath),"tmp/jmodpack/%s_%d.tar.bz2",jmod_info->name,jmod_info->cacheid); + unlink(tpath); + + delete jmod_info; + } + return 0; +} +static int manage_updatejmod(char *name,int cacheid){ + std::map<std::string,center_jmod_info*>::iterator jmod_it; + center_jmod_info *old_jmod_info; + center_jmod_info *update_jmod_info; + + char tpath[PATH_MAX + 1]; + struct stat st; + std::pair<std::map<std::string,center_jmod_info*>::iterator,bool> ins_ret; + + if((jmod_it = center_manage_jmodmap.find(name)) == center_manage_jmodmap.end()){ + old_jmod_info = NULL; + }else{ + old_jmod_info = jmod_it->second; + + if(old_jmod_info->state == CENTER_CACHESTATE_READY && cacheid == old_jmod_info->cacheid){ + return -1; + } + if(old_jmod_info->state == CENTER_CACHESTATE_UPDATE && (cacheid <= old_jmod_info->cacheid || cacheid <= old_jmod_info->update_cacheid)){ + return -1; + } + + old_jmod_info->state = CENTER_CACHESTATE_UPDATE; + old_jmod_info->update_cacheid = cacheid; + } + + update_jmod_info = new center_jmod_info(name,cacheid); + center_manage_getjmod(update_jmod_info); + + snprintf(tpath,sizeof(tpath),"tmp/jmod/%s_%d",update_jmod_info->name,update_jmod_info->cacheid); + if(!stat(tpath,&st)){ + snprintf(tpath,sizeof(tpath),"tmp/jmodpack/%s_%d.tar.bz2",update_jmod_info->name,update_jmod_info->cacheid); + if(!stat(tpath,&st)){ + + if(old_jmod_info != NULL){ + center_manage_putjmod(old_jmod_info); + + ins_ret = center_manage_jmodmap.insert(std::make_pair(update_jmod_info->name,update_jmod_info)); + if(ins_ret.second == false){ + ins_ret.first->second = update_jmod_info; + } + + return 1; + } + } + } + + manage_tp->add(manage_updatejmod_thfn,update_jmod_info,manage_updatejmod_cbfn,update_jmod_info); + + return 0; +} +static void manage_updatejmod_th(void *data){ + center_jmod_info *jmod_info; + char src_path[PATH_MAX + 1]; + char dir_path[PATH_MAX + 1]; + char pack_path[PATH_MAX + 1]; + + jmod_info = (center_jmod_info*)data; + + snprintf(src_path,sizeof(src_path),"jmod/%s",jmod_info->name); + snprintf(dir_path,sizeof(dir_path),"tmp/jmod/%s_%d.tar.bz2",jmod_info->name,jmod_info->cacheid); + tool_copydir(src_path,dir_path); + + snprintf(pack_path,sizeof(pack_path),"tmp/jmodpack/%s_%d.tar.bz2",jmod_info->name,jmod_info->cacheid); + tool_pack(pack_path,dir_path); +} +static void manage_updatejmod_cb(void *data){ + center_jmod_info *old_jmod_info; + center_jmod_info *update_jmod_info; + std::pair<std::map<std::string,center_jmod_info*>::iterator,bool> ins_ret; + std::vector<std::pair<std::string,int> > jmod_pair; + + update_jmod_info = (center_jmod_info*)data; + + ins_ret = center_manage_jmodmap.insert(std::make_pair(update_jmod_info->name,update_jmod_info)); + if(ins_ret.second == false){ + old_jmod_info = ins_ret.first->second; + + if(update_jmod_info->cacheid <= old_jmod_info->cacheid){ + center_manage_putjmod(update_jmod_info); + } + + center_manage_putjmod(old_jmod_info); + ins_ret.first->second = update_jmod_info; + } + + jmod_pair.push_back(std::make_pair(update_jmod_info->name,update_jmod_info->cacheid)); + //wait + + // +} |