aboutsummaryrefslogtreecommitdiffstats
path: root/judge
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-04-11 22:33:25 +0800
committerLAN-TW <lantw44@gmail.com>2013-04-11 22:33:25 +0800
commit962be8a7de5035e7d86b9274962f7d6fe3315fdd (patch)
treea78bd11270904346d2e26123482c25f73664f728 /judge
parent4c094052d68e90bd672ae2d312419861e5f71722 (diff)
downloadtaiwan-online-judge-lantw44-962be8a7de5035e7d86b9274962f7d6fe3315fdd.tar.gz
taiwan-online-judge-lantw44-962be8a7de5035e7d86b9274962f7d6fe3315fdd.tar.zst
taiwan-online-judge-lantw44-962be8a7de5035e7d86b9274962f7d6fe3315fdd.zip
Remove top-level directory `toj'
Diffstat (limited to 'judge')
-rw-r--r--judge/Makefile6
-rw-r--r--judge/center.h47
-rw-r--r--judge/center_com.h70
-rw-r--r--judge/center_judge.cpp578
-rw-r--r--judge/center_judge.h106
-rw-r--r--judge/center_manage.cpp640
-rw-r--r--judge/center_manage.h75
-rw-r--r--judge/center_server.cpp198
-rw-r--r--judge/center_server.h45
-rw-r--r--judge/event_exec.cpp89
-rw-r--r--judge/event_exec.h12
-rw-r--r--judge/jmod_test.h17
-rw-r--r--judge/jmod_test_check.cpp109
-rw-r--r--judge/jmod_test_check.h4
-rw-r--r--judge/jmod_test_line.cpp190
-rw-r--r--judge/jmod_test_line.h11
-rw-r--r--judge/jmod_test_manage.cpp96
-rw-r--r--judge/jmod_test_manage.h35
-rw-r--r--judge/judge.h44
-rw-r--r--judge/judge_manage.cpp371
-rw-r--r--judge/judge_manage.h60
-rw-r--r--judge/judge_server.cpp515
-rw-r--r--judge/judge_server.h87
-rw-r--r--judge/judgm_lib.h418
-rw-r--r--judge/judgm_line.h19
-rw-r--r--judge/judgm_manage.h29
-rw-r--r--judge/netio.h192
-rw-r--r--judge/tool.cpp294
-rw-r--r--judge/tool.h26
-rw-r--r--judge/tpool.h175
30 files changed, 4558 insertions, 0 deletions
diff --git a/judge/Makefile b/judge/Makefile
new file mode 100644
index 0000000..3fe0444
--- /dev/null
+++ b/judge/Makefile
@@ -0,0 +1,6 @@
+all:
+ g++ -I../include -g -rdynamic -fvisibility=hidden -O2 center_server.cpp center_manage.cpp center_judge.cpp tool.cpp event_exec.cpp -ldl -lpq -ltar -lbz2 -ljson -lcurl -pthread -o center_server
+ g++ -I../include -g -O2 judge_server.cpp judge_manage.cpp tool.cpp -ldl -lbz2 -ltar -pthread -o judge_server
+ g++ -shared -fPIC -fvisibility=hidden -O2 -I../include jmod_test_manage.cpp -ldl -ljson -pthread -o jmod_test_manage.so
+ g++ -shared -fPIC -fvisibility=hidden -O2 -I../include jmod_test_line.cpp -ljson -pthread -o jmod_test_line.so
+ g++ -shared -fPIC -fvisibility=hidden -O2 -I../include jmod_test_check.cpp -o jmod_test_check.so
diff --git a/judge/center.h b/judge/center.h
new file mode 100644
index 0000000..2625ab4
--- /dev/null
+++ b/judge/center.h
@@ -0,0 +1,47 @@
+#define CENTER_CACHESTATE_READY 0
+#define CENTER_CACHESTATE_UPDATE 1
+
+class center_jmod_info{
+public:
+ char name[NAME_MAX + 1];
+ int cacheid;
+ void *manage_dll;
+ void *manage_sub_fn;
+ void *manage_res_fn;
+
+ int ref_count;
+ int state;
+ int update_cacheid;
+
+ center_jmod_info(char *name,int cacheid){
+ this->name[0] = '\0';
+ strncat(this->name,name,sizeof(this->name));
+ this->cacheid = cacheid;
+ this->manage_dll = NULL;
+ this->manage_sub_fn = NULL;
+ this->manage_res_fn = NULL;
+ }
+};
+
+class center_pro_info{
+public:
+ int proid;
+ int cacheid;
+ center_jmod_info *jmod_info;
+ int lang_flag;
+
+ int ref_count;
+ int state;
+ int update_cacheid;
+
+ center_pro_info(int proid,int cacheid,center_jmod_info *jmod_info,int lang_flag){
+ this->proid = proid;
+ this->cacheid = cacheid;
+ this->jmod_info = jmod_info;
+ this->lang_flag = lang_flag;
+
+ this->ref_count = 0;
+ this->state = CENTER_CACHESTATE_READY;
+ this->update_cacheid = 0;
+ }
+};
diff --git a/judge/center_com.h b/judge/center_com.h
new file mode 100644
index 0000000..6973eec
--- /dev/null
+++ b/judge/center_com.h
@@ -0,0 +1,70 @@
+#define CENTER_COMCODE_SETID 1
+#define CENTER_COMCODE_SETINFO 2
+#define CENTER_COMCODE_SUBMIT 3
+#define CENTER_COMCODE_RESULT 4
+
+#define CENTER_COMCODE_SETPRO 10
+#define CENTER_COMCODE_REQPRO 11
+#define CENTER_COMCODE_SENDPRO 12
+#define CENTER_COMCODE_SETJMOD 13
+#define CENTER_COMCODE_REQJMOD 14
+#define CENTER_COMCODE_SENDJMOD 15
+
+#define CENTER_COMCODE_REQCODE 20
+#define CENTER_COMCODE_SENDCODE 21
+
+struct center_com_header{
+ int code;
+ int size;
+}__attribute__((packed));
+struct center_com_setid{
+ int id; //0:new judge
+}__attribute__((packed));
+struct center_com_setinfo{
+ int avail;
+}__attribute__((packed));
+struct center_com_submit{ //judt submit header
+ int subid;
+ int proid;
+ int lang;
+}__attribute__((packed));
+struct center_com_result{ //just result header
+ int subid;
+}__attribute__((packed));
+
+struct center_com_setpro{
+ int proid;
+ int cacheid;
+ int type; //0:add problem 1:drop problem
+}__attribute__((packed));
+struct center_com_reqpro{
+ int proid;
+ int cacheid;
+}__attribute__((packed));
+struct center_com_sendpro{
+ int proid;
+ int cacheid;
+ size_t filesize;
+}__attribute__((packed));
+
+struct center_com_setjmod{
+ char jmod_name[NAME_MAX + 1];
+ int cacheid;
+ int type; //0:add jmod 1:drop jmod
+}__attribute__((packed));
+struct center_com_reqjmod{
+ char jmod_name[NAME_MAX + 1];
+}__attribute__((packed));
+struct center_com_sendjmod{
+ char jmod_name[NAME_MAX + 1];
+ int cacheid;
+ size_t filesize;
+}__attribute__((packed));
+
+struct center_com_reqcode{
+ int subid;
+}__attribute__((packed));
+struct center_com_sendcode{
+ int subid;
+ size_t filesize;
+}__attribute__((packed));
diff --git a/judge/center_judge.cpp b/judge/center_judge.cpp
new file mode 100644
index 0000000..46600c2
--- /dev/null
+++ b/judge/center_judge.cpp
@@ -0,0 +1,578 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<unistd.h>
+#include<fcntl.h>
+#include<limits.h>
+#include<errno.h>
+#include<sys/stat.h>
+#include<sys/types.h>
+#include<sys/epoll.h>
+#include<sys/sendfile.h>
+#include<map>
+#include<list>
+#include<queue>
+#include<string>
+
+#include"netio.h"
+#include"judge_def.h"
+#include"judgm_manage.h"
+#include"center.h"
+#include"center_com.h"
+#include"center_judge.h"
+
+int judge_info::last_id = 0;
+judge_info::judge_info(){
+ last_id++;
+ this->id = last_id;
+ this->avail = 0;
+
+ judge_idmap.insert(std::pair<int,judge_info*>(id,this));
+ judge_runlist.push_back(this);
+ judge_it = judge_runlist.end();
+ judge_it--;
+}
+judge_info::~judge_info(){
+ judge_idmap.erase(id);
+ judge_runlist.erase(judge_it);
+}
+int judge_info::setavail(int avail){
+ int old;
+
+ old = this->avail;
+ this->avail = avail;
+ if(this->avail > 0 && old <= 0){
+ judge_runlist.erase(judge_it);
+ judge_runlist.push_front(this);
+ judge_it = judge_runlist.begin();
+ }else if(this->avail <= 0 && old > 0){
+ judge_runlist.erase(judge_it);
+ judge_runlist.push_back(this);
+ judge_it = judge_runlist.end();
+ judge_it--;
+ }
+
+ return 0;
+}
+int judge_info::setinfo(int avail){
+ setavail(avail);
+ return 0;
+}
+int judge_info::submit(judge_submit_info *sub_info){
+ setavail(avail - 1);
+ conn_main->send_submit(sub_info);
+ return 0;
+}
+int judge_info::result(int subid,char *res_data){
+ setavail(avail + 1);
+
+ printf("submitid:%d\n",subid);
+ center_manage_result(subid,res_data);
+
+ judge_run_waitqueue();
+ return 0;
+}
+int judge_info::updatepro(std::vector<std::pair<int,int> > &pro_list){
+ int i;
+
+ for(i = 0;i < pro_list.size();i++){
+ pro_map.erase(pro_list[i].first);
+ }
+ conn_main->send_setpro(pro_list,0);
+
+ return 0;
+}
+int judge_info::updatejmod(std::vector<std::pair<char*,int> > &jmod_list){
+ int i;
+
+ for(i = 0;i < jmod_list.size();i++){
+ jmod_map.erase(jmod_list[i].first);
+ }
+ conn_main->send_setjmod(jmod_list,0);
+
+ return 0;
+}
+
+
+judge_conn::judge_conn(int fd):netio(fd){
+ this->info = NULL;
+ this->recv_dispatch_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_dispatch);
+ this->recv_setid_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_setid);
+ this->recv_setinfo_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_setinfo);
+ this->recv_result_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_result);
+ this->recv_setpro_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_setpro);
+ this->recv_reqpro_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_reqpro);
+ this->done_sendpro_fn = new netio_iofn<judge_conn>(this,&judge_conn::done_sendpro);
+ this->recv_setjmod_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_setjmod);
+ this->recv_reqjmod_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_reqjmod);
+ this->recv_reqcode_fn = new netio_iofn<judge_conn>(this,&judge_conn::recv_reqcode);
+}
+judge_conn::~judge_conn(){
+ info->conn_list.erase(conn_it);
+ if(info->conn_main == this){
+ info->conn_main = NULL;
+ }
+ if(info->conn_list.empty()){
+ delete info;
+ }
+
+ delete recv_dispatch_fn;
+ delete recv_setid_fn;
+ delete recv_setinfo_fn;
+ delete recv_result_fn;
+ delete recv_setpro_fn;
+ delete recv_reqpro_fn;
+ delete done_sendpro_fn;
+ delete recv_setjmod_fn;
+ delete recv_reqjmod_fn;
+ delete recv_reqcode_fn;
+}
+char* judge_conn::create_combuf(int code,int size,int &len,void **data){
+ char *buf;
+ center_com_header *header;
+
+ buf = new char[sizeof(center_com_header) + size];
+ header = (center_com_header*)buf;
+ header->code = code;
+ header->size = size;
+ len = sizeof(center_com_header) + size;
+ *data = (void*)(buf + sizeof(center_com_header));
+
+ return buf;
+}
+int judge_conn::send_setid(int judgeid){
+ char *write_buf;
+ int write_len;
+ center_com_setid *setid;
+
+ write_buf = create_combuf(CENTER_COMCODE_SETID,sizeof(center_com_setid),write_len,(void**)&setid);
+ setid->id = judgeid;
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int judge_conn::send_submit(judge_submit_info *sub_info){
+ char *write_buf;
+ int write_len;
+ center_com_submit *sub;
+
+ if(sub_info->set_len > JUDGE_SET_DATAMAX){
+ delete sub_info;
+ return -1;
+ }
+
+ write_buf = create_combuf(CENTER_COMCODE_SUBMIT,sizeof(center_com_submit) + sub_info->set_len,write_len,(void**)&sub);
+ sub->subid = sub_info->subid;
+ sub->proid = sub_info->proid;
+ sub->lang = sub_info->lang;
+ memcpy((void*)(write_buf + sizeof(center_com_header) + sizeof(center_com_submit)),sub_info->set_data,sub_info->set_len);
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ delete sub_info;
+ return 0;
+}
+int judge_conn::send_setpro(std::vector<std::pair<int,int> > &pro_list,int type){
+ int i;
+
+ int count;
+ char *write_buf;
+ int write_len;
+ center_com_setpro *setpro;
+
+ count = pro_list.size();
+ write_buf = create_combuf(CENTER_COMCODE_SETPRO,sizeof(center_com_setpro) * count,write_len,(void**)&setpro);
+
+ for(i = 0;i < count;i++){
+ setpro[i].proid = pro_list[i].first;
+ setpro[i].cacheid = pro_list[i].second;
+ setpro[i].type = type;
+ }
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int judge_conn::send_setjmod(std::vector<std::pair<char*,int> > &jmod_list,int type){
+ int i;
+
+ int count;
+ char *write_buf;
+ int write_len;
+ center_com_setjmod *setjmod;
+
+ count = jmod_list.size();
+ write_buf = create_combuf(CENTER_COMCODE_SETJMOD,sizeof(center_com_setjmod) * count,write_len,(void**)&setjmod);
+
+ for(i = 0;i < count;i++){
+ setjmod[i].jmod_name[0] = '\0';
+ strncat(setjmod[i].jmod_name,jmod_list[i].first,sizeof(setjmod[i].jmod_name));
+ setjmod[i].cacheid = jmod_list[i].second;
+ setjmod[i].type = type;
+ }
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int judge_conn::readidle(){
+ readbytes(new center_com_header,sizeof(center_com_header),recv_dispatch_fn,NULL);
+ return 0;
+}
+void judge_conn::recv_dispatch(void *buf,size_t len,void *data){
+ center_com_header *header;
+ char *readbuf;
+
+ header = (center_com_header*)buf;
+ readbuf = new char[header->size];
+
+ printf("code:%d size:%d\n",header->code,header->size);
+ switch(header->code){
+ case CENTER_COMCODE_SETID:
+ readbytes(readbuf,header->size,recv_setid_fn,NULL);
+ break;
+ case CENTER_COMCODE_SETINFO:
+ readbytes(readbuf,header->size,recv_setinfo_fn,NULL);
+ break;
+ case CENTER_COMCODE_RESULT:
+ readbytes(readbuf,header->size,recv_result_fn,NULL);
+ break;
+ case CENTER_COMCODE_SETPRO:
+ readbytes(readbuf,header->size,recv_setpro_fn,NULL);
+ break;
+ case CENTER_COMCODE_REQPRO:
+ readbytes(readbuf,header->size,recv_reqpro_fn,NULL);
+ break;
+ case CENTER_COMCODE_SETJMOD:
+ readbytes(readbuf,header->size,recv_setjmod_fn,NULL);
+ break;
+ case CENTER_COMCODE_REQJMOD:
+ readbytes(readbuf,header->size,recv_reqjmod_fn,NULL);
+ break;
+ case CENTER_COMCODE_REQCODE:
+ readbytes(readbuf,header->size,recv_reqcode_fn,NULL);
+ break;
+ }
+
+ delete header;
+}
+void judge_conn::recv_setid(void *buf,size_t len,void *data){
+ center_com_setid *setid;
+ std::map<int,judge_info*>::iterator it;
+
+ setid = (center_com_setid*)buf;
+ if(setid->id == 0){
+ info = new judge_info();
+
+ info->conn_list.push_front(this);
+ conn_it = info->conn_list.begin();
+ info->conn_main = this;
+
+ this->send_setid(info->id);
+ }else{
+ if((it = judge_idmap.find(setid->id)) != judge_idmap.end()){
+ info = it->second;
+ info->conn_list.push_front(this);
+ conn_it = info->conn_list.begin();
+ }
+ }
+
+ delete setid;
+}
+void judge_conn::recv_setinfo(void *buf,size_t len,void *data){
+ int i;
+ int count;
+
+ center_com_setinfo *setinfo;
+ std::map<std::string,center_jmod_info*>::iterator jmod_it;
+ std::vector<std::pair<char*,int> > jmod_list;
+ std::map<int,center_pro_info*>::iterator pro_it;
+ std::vector<std::pair<int,int> > pro_list;
+
+ setinfo = (center_com_setinfo*)buf;
+ info->setinfo(setinfo->avail);
+
+ count = center_manage_jmodmap.size();
+ jmod_it = center_manage_jmodmap.begin();
+ for(i = 0;i < count;i++,jmod_it++){
+ jmod_list.push_back(std::make_pair(jmod_it->second->name,jmod_it->second->cacheid));
+ }
+ send_setjmod(jmod_list,0);
+
+ count = center_manage_promap.size();
+ pro_it = center_manage_promap.begin();
+ for(i = 0;i < count;i++,pro_it++){
+ pro_list.push_back(std::make_pair(pro_it->second->proid,pro_it->second->cacheid));
+ }
+ send_setpro(pro_list,0);
+
+ delete setinfo;
+}
+void judge_conn::recv_result(void *buf,size_t len,void *data){
+ int subid;
+ char *res_data;
+
+ subid = ((center_com_result*)buf)->subid;
+ res_data = (char*)((char*)buf + sizeof(center_com_result));
+
+ info->result(subid,res_data);
+
+ delete (char*)buf;
+}
+void judge_conn::recv_setpro(void *buf,size_t len,void *data){
+ int i;
+ int count;
+
+ center_com_setpro *setpro;
+ center_pro_info *pro_info;
+ std::map<int,center_pro_info*>::iterator pro_it;
+
+ count = len / sizeof(center_com_setpro);
+ setpro = (center_com_setpro*)buf;
+ for(i = 0;i < count;i++){
+ if(setpro[i].type == 0){
+ if((pro_info = center_manage_getprobyid(setpro[i].proid)) == NULL){
+ continue;
+ }
+
+ if(pro_info->cacheid == setpro[i].cacheid){
+ info->pro_map.insert(std::pair<int,int>(pro_info->proid,pro_info->cacheid));
+ }
+ center_manage_putpro(pro_info);
+
+ }else if(setpro[i].type == 1){
+ info->pro_map.erase(setpro[i].proid);
+ }
+ }
+
+ judge_run_waitqueue();
+ delete setpro;
+}
+void judge_conn::recv_reqpro(void *buf,size_t len,void *data){
+ center_com_reqpro *reqpro;
+ std::map<int,center_pro_info*>::iterator pro_it;
+ center_pro_info *pro_info;
+
+ char tpath[PATH_MAX + 1];
+ int fd;
+ struct stat st;
+
+ char *write_buf;
+ int write_len;
+ center_com_sendpro *sendpro;
+
+ reqpro = (center_com_reqpro*)buf;
+ try{
+ if((pro_info = center_manage_getprobyid(reqpro->proid)) == NULL){
+ throw -1;
+ }
+ if(pro_info->cacheid != reqpro->cacheid){
+ throw -1;
+ }
+
+ snprintf(tpath,sizeof(tpath),"tmp/propack/%d_%d.tar.bz2",pro_info->proid,pro_info->cacheid);
+ fd = open(tpath,O_RDONLY);
+ fstat(fd,&st);
+ write_buf = create_combuf(CENTER_COMCODE_SENDPRO,sizeof(center_com_sendpro),write_len,(void**)&sendpro);
+ sendpro->proid = pro_info->proid;
+ sendpro->cacheid = pro_info->cacheid;
+ sendpro->filesize = st.st_size;
+ printf("sendpro:%lu\n",sendpro->filesize);
+
+ writebytes(write_buf,write_len,NULL,NULL);
+ writefile(fd,st.st_size,done_sendpro_fn,pro_info);
+ }catch(int err){
+ if(pro_info != NULL){
+ center_manage_putpro(pro_info);
+ }
+ }
+
+ delete reqpro;
+}
+void judge_conn::done_sendpro(void *buf,size_t len,void *data){
+ close((int)((long)buf));
+ center_manage_putpro((center_pro_info*)data);
+}
+void judge_conn::recv_setjmod(void *buf,size_t len,void *data){
+ int i;
+ int count;
+
+ center_com_setjmod *setjmod;
+ std::map<std::string,center_jmod_info*>::iterator jmod_it;
+
+ count = len / sizeof(center_com_setjmod);
+ setjmod = (center_com_setjmod*)buf;
+ for(i = 0;i < count;i++){
+ if(setjmod[i].type == 0){
+ if((jmod_it = center_manage_jmodmap.find(setjmod[i].jmod_name)) == center_manage_jmodmap.end()){
+ continue;
+ }
+ if(jmod_it->second->cacheid != setjmod[i].cacheid){
+ continue;
+ }
+
+ info->jmod_map.insert(std::pair<std::string,center_jmod_info*>(jmod_it->second->name,jmod_it->second));
+ }else if(setjmod[i].type == 1){
+ info->jmod_map.erase(setjmod[i].jmod_name);
+ }
+ }
+
+ judge_run_waitqueue();
+ delete setjmod;
+}
+void judge_conn::recv_reqjmod(void *buf,size_t len,void *data){
+ center_com_reqjmod *reqjmod;
+ std::map<std::string,center_jmod_info*>::iterator jmod_it;
+ center_jmod_info *jmod_info;
+
+ char tpath[PATH_MAX + 1];
+ int fd;
+ struct stat st;
+
+ char *write_buf;
+ int write_len;
+ center_com_sendjmod *sendjmod;
+
+ reqjmod = (center_com_reqjmod*)buf;
+ if((jmod_it = center_manage_jmodmap.find(reqjmod->jmod_name)) == center_manage_jmodmap.end()){
+ //fix
+ }else{
+ jmod_info = jmod_it->second;
+
+ snprintf(tpath,sizeof(tpath),"tmp/jmodpack/%s.tar.bz2",jmod_info->name);
+ fd = open(tpath,O_RDONLY);
+ if(fstat(fd,&st)){
+ //fix
+ }else{
+ write_buf = create_combuf(CENTER_COMCODE_SENDJMOD,sizeof(center_com_sendjmod),write_len,(void**)&sendjmod);
+ sendjmod->jmod_name[0] = '\0';
+ strncat(sendjmod->jmod_name,jmod_info->name,sizeof(sendjmod->jmod_name));
+ sendjmod->cacheid = jmod_info->cacheid;
+ sendjmod->filesize = st.st_size;
+ printf("sendjmod:%lu\n",sendjmod->filesize);
+
+ writebytes(write_buf,write_len,NULL,NULL);
+ writefile(fd,st.st_size,NULL,NULL);
+ }
+ }
+
+ delete reqjmod;
+}
+void judge_conn::recv_reqcode(void *buf,size_t len,void *data){
+ center_com_reqcode *reqcode;
+ char tpath[PATH_MAX + 1];
+ int fd;
+ struct stat st;
+
+ char *write_buf;
+ int write_len;
+ center_com_header *header;
+ center_com_sendcode *sendcode;
+
+ reqcode = (center_com_reqcode*)buf;
+ snprintf(tpath,sizeof(tpath),"tmp/codepack/%d.tar.bz2",reqcode->subid);
+ fd = open(tpath,O_RDONLY);
+ if(fstat(fd,&st)){
+ //fix
+ }else{
+ write_buf = create_combuf(CENTER_COMCODE_SENDCODE,sizeof(center_com_sendcode),write_len,(void**)&sendcode);
+ sendcode->subid = reqcode->subid;
+ sendcode->filesize = st.st_size;
+ printf("sendcode:%lu\n",sendcode->filesize);
+
+ writebytes(write_buf,write_len,NULL,NULL);
+ writefile(fd,st.st_size,NULL,NULL);
+ }
+
+ delete reqcode;
+}
+
+
+static int judge_run_waitqueue(){
+ int count;
+ judge_submit_info *sub_info;
+ bool wait_flag;
+ std::list<judge_info*>::iterator judge_it;
+ judge_info *info;
+ std::map<int,center_pro_info*>::iterator pro_it;
+ center_pro_info *pro_info;
+
+ count = judge_submitqueue.size();
+ printf(" remain count %d\n",count);
+ for(;count > 0;count--){
+ sub_info = judge_submitqueue.front();
+ judge_submitqueue.pop();
+
+ if((pro_it = center_manage_promap.find(sub_info->proid)) == center_manage_promap.end()){
+ continue;
+ }
+ pro_info = pro_it->second;
+
+ wait_flag = true;
+ for(judge_it = judge_runlist.begin();judge_it != judge_runlist.end();judge_it++){
+ info = *judge_it;
+ if(info->avail <= 0){
+ break;
+ }
+ if(info->pro_map.find(pro_info->proid) != info->pro_map.end() && info->jmod_map.find(pro_info->jmod_info->name) != info->jmod_map.end()){
+ info->submit(sub_info);
+ wait_flag = false;
+ break;
+ }
+ }
+ if(wait_flag == true){
+ judge_submitqueue.push(sub_info);
+ }
+ }
+ return 0;
+}
+int center_judge_init(){
+ return 0;
+}
+void* center_judge_addconn(int fd){
+ return new judge_conn(fd);
+}
+int center_judge_dispatch(int evflag,void *data){
+ judge_conn *cinfo;
+
+ cinfo = (judge_conn*)data;
+ if(evflag & EPOLLRDHUP){
+ printf("close %d\n",cinfo->fd);
+ delete cinfo;
+ }else{
+ if(evflag & EPOLLIN){
+ cinfo->readio();
+ }
+ if(evflag & EPOLLOUT){
+ cinfo->writeio();
+ }
+ }
+
+ return 0;
+}
+int center_judge_submit(int subid,int proid,int lang,char *set_data,size_t set_len){
+ judge_submitqueue.push(new judge_submit_info(subid,proid,lang,set_data,set_len));
+ judge_run_waitqueue();
+ return 0;
+}
+int center_judge_updatepro(std::vector<std::pair<int,int> > &pro_list){
+ int i;
+ int j;
+ std::list<judge_info*>::iterator judge_it;
+ judge_info *info;
+
+ for(judge_it = judge_runlist.begin();judge_it != judge_runlist.end();judge_it++){
+ (*judge_it)->updatepro(pro_list);
+ }
+
+ return 0;
+}
+int center_judge_updatejmod(std::vector<std::pair<char*,int> > &jmod_list){
+ int i;
+ int j;
+ std::list<judge_info*>::iterator judge_it;
+ judge_info *info;
+
+ for(judge_it = judge_runlist.begin();judge_it != judge_runlist.end();judge_it++){
+ (*judge_it)->updatejmod(jmod_list);
+ }
+
+ return 0;
+}
diff --git a/judge/center_judge.h b/judge/center_judge.h
new file mode 100644
index 0000000..a955ce9
--- /dev/null
+++ b/judge/center_judge.h
@@ -0,0 +1,106 @@
+class judge_info;
+class judge_conn;
+class judge_submit_info;
+
+class judge_info{
+private:
+ static int last_id;
+
+public:
+ int id;
+ int avail;
+ judge_conn *conn_main;
+ std::list<judge_conn*> conn_list;
+ std::list<judge_info*>::iterator judge_it;
+ std::map<int,int> pro_map;
+ std::map<std::string,center_jmod_info*> jmod_map;
+
+ judge_info();
+ ~judge_info();
+ int setavail(int value);
+ int setinfo(int avail);
+ int submit(judge_submit_info *submit_info);
+ int result(int subid,char *res_data);
+ int updatepro(std::vector<std::pair<int,int> > &pro_list);
+ int updatejmod(std::vector<std::pair<char*,int> > &jmod_list);
+};
+
+class judge_conn : public netio{
+private:
+ netio_iofn<judge_conn> *recv_dispatch_fn;
+ netio_iofn<judge_conn> *recv_setid_fn;
+ netio_iofn<judge_conn> *recv_setinfo_fn;
+ netio_iofn<judge_conn> *recv_result_fn;
+ netio_iofn<judge_conn> *recv_setpro_fn;
+ netio_iofn<judge_conn> *recv_reqpro_fn;
+ netio_iofn<judge_conn> *done_sendpro_fn;
+ netio_iofn<judge_conn> *recv_setjmod_fn;
+ netio_iofn<judge_conn> *recv_reqjmod_fn;
+ netio_iofn<judge_conn> *recv_reqcode_fn;
+
+ char* create_combuf(int code,int size,int &len,void **data);
+ void recv_dispatch(void *buf,size_t len,void *data);
+ void recv_setid(void *buf,size_t len,void *data);
+ void recv_setinfo(void *buf,size_t len,void *data);
+ void recv_result(void *buf,size_t len,void *data);
+ void recv_setpro(void *buf,size_t len,void *data);
+ void recv_reqpro(void *buf,size_t len,void *data);
+ void done_sendpro(void *buf,size_t len,void *data);
+ void recv_setjmod(void *buf,size_t len,void *data);
+ void recv_reqjmod(void *buf,size_t len,void *data);
+ void recv_reqcode(void *buf,size_t len,void *data);
+
+public:
+ judge_info *info;
+ std::list<judge_conn*>::iterator conn_it;
+
+ judge_conn(int fd);
+ ~judge_conn();
+ int send_setid(int judgeid);
+ int send_submit(judge_submit_info* submit_info);
+ int send_setpro(std::vector<std::pair<int,int> > &pro_list,int type);
+ int send_setjmod(std::vector<std::pair<char*,int> > &jmod_list,int type);
+ virtual int readidle();
+};
+
+class judge_submit_info{
+public:
+ int subid;
+ int proid;
+ int lang;
+ char *set_data;
+ size_t set_len;
+
+ judge_submit_info(int subid,int proid,int lang,char *set_data,size_t set_len){
+ this->subid = subid;
+ this->proid = proid;
+ this->lang = lang;
+ this->set_data = new char[set_len];
+ memcpy(this->set_data,set_data,set_len);
+ this->set_len = set_len;
+ }
+ ~judge_submit_info(){
+ delete this->set_data;
+ }
+};
+
+static int judge_run_waitqueue();
+
+static std::map<int,judge_info*> judge_idmap;
+static std::list<judge_info*> judge_runlist;
+static std::queue<judge_submit_info*> judge_submitqueue;
+
+int center_judge_init();
+void* center_judge_addconn(int fd);
+int center_judge_dispatch(int evflag,void *data);
+int center_judge_submit(int subid,int proid,int lang,char *set_data,size_t set_len);
+int center_judge_updatepro(std::vector<std::pair<int,int> > &pro_list);
+int center_judge_updatejmod(std::vector<std::pair<char*,int> > &jmod_list);
+
+extern int center_manage_result(int subid,char *res_data);
+extern center_pro_info* center_manage_getprobyid(int proid);
+extern int center_manage_getpro(center_pro_info *pro_info);
+extern int center_manage_putpro(center_pro_info *pro_info);
+
+extern std::map<std::string,center_jmod_info*> center_manage_jmodmap;
+extern std::map<int,center_pro_info*> center_manage_promap;
diff --git a/judge/center_manage.cpp b/judge/center_manage.cpp
new file mode 100644
index 0000000..48cfd31
--- /dev/null
+++ b/judge/center_manage.cpp
@@ -0,0 +1,640 @@
+#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;
+
+ try{
+ 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),"tmp/pro/%d_%d",pro_info->proid,pro_info->cacheid);
+ 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),"tmp/pro/%d_%d/setting",pro_info->proid,pro_info->cacheid);
+ if((set_file = fopen(tpath,"r")) == NULL){
+ throw 0;
+ }
+ 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);
+ }catch(...){
+ manage_finish_result(sub_info->subid,
+ sub_info->uid,
+ sub_info->pro_info->proid,
+ JUDGE_ERR,
+ 0,
+ 0,
+ 0,
+ sub_info->rejudge_flag);
+ }
+}
+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;
+
+ 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);
+
+ manage_finish_result(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_finish_result(int subid,int uid,int proid,int result,double score,int runtime,int memory,bool rejudge_flag){
+ 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((db_conn = center_manage_conndb()) == NULL){
+ return -1;
+ }
+
+ snprintf(db_result,sizeof(db_result),"%d",result);
+ snprintf(db_score,sizeof(db_score),"%lf",score);
+ snprintf(db_runtime,sizeof(db_runtime),"%lu",runtime);
+ snprintf(db_memory,sizeof(db_memory),"%lu",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,
+ uid,
+ proid,
+ result,
+ score,
+ runtime,
+ memory,
+ rejudge_flag);
+
+ 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
+
+ //
+}
diff --git a/judge/center_manage.h b/judge/center_manage.h
new file mode 100644
index 0000000..b2ee36e
--- /dev/null
+++ b/judge/center_manage.h
@@ -0,0 +1,75 @@
+class manage_submit_info{
+public:
+ int subid;
+ int uid;
+ center_jmod_info *jmod_info;
+ center_pro_info *pro_info;
+ int lang;
+ bool rejudge_flag;
+ char param[JUDGE_SUB_PARAMMAX];
+ judgm_manage_info *manage_info;
+
+ manage_submit_info(int subid,int uid,center_jmod_info *jmod_info,center_pro_info *pro_info,int lang,bool rejudge_flag,char *param){
+ this->subid = subid;
+ this->uid = uid;
+ this->jmod_info = jmod_info;
+ this->pro_info = pro_info;
+ this->lang = lang;
+ this->rejudge_flag = rejudge_flag;
+ this->param[0] = '\0';
+ strncat(this->param,param,sizeof(this->param));
+
+ this->manage_info = new judgm_manage_info(this->subid,this->uid,pro_info->proid,this->lang,this->param);
+ }
+ ~manage_submit_info(){
+ delete this->manage_info;
+ }
+};
+
+static void manage_submit_th(void *data);
+static void manage_submit_cb(void *data);
+static int manage_finish_result(int subid,int uid,int proid,int result,double score,int runtime,int memory,bool rejudge_flag);
+static int manage_notice(int subid,int uid,int proid,int result,double score,int runtime,int memory,bool rejudge_flag);
+
+static int manage_updatepro(int proid,int cacheid,center_jmod_info *jmod_info,int lang_flag);
+static void manage_updatepro_th(void *data);
+static void manage_updatepro_cb(void *data);
+static int manage_updatejmod(char *name,int cacheid);
+static void manage_updatejmod_th(void *data);
+static void manage_updatejmod_cb(void *data);
+
+static tpool *manage_tp;
+static tpool_static_fn *manage_updatepro_thfn;
+static tpool_static_fn *manage_updatepro_cbfn;
+static tpool_static_fn *manage_updatejmod_thfn;
+static tpool_static_fn *manage_updatejmod_cbfn;
+static tpool_static_fn *manage_submit_thfn;
+static tpool_static_fn *manage_submit_cbfn;
+static std::map<int,manage_submit_info*> manage_submap;
+
+int center_manage_init(tpool **tpinfo);
+PGconn* center_manage_conndb();
+int center_manage_closedb(PGconn *conn);
+int center_manage_updatedata();
+int center_manage_submitwait();
+int center_manage_submit(int subid,char *param);
+int center_manage_result(int subid,char *res_data);
+DLL_PUBLIC int center_manage_queuesubmit(int subid,int proid,int lang,char *set_data,size_t set_len);
+
+center_pro_info* center_manage_getprobyid(int proid);
+int center_manage_getpro(center_pro_info*);
+int center_manage_putpro(center_pro_info *pro_info);
+center_jmod_info* center_manage_getjmodbyname(char *name);
+int center_manage_getjmod(center_jmod_info *jmod_info);
+int center_manage_putjmod(center_jmod_info *jmod_info);
+
+std::map<int,center_pro_info*> center_manage_promap;
+std::map<std::string,center_jmod_info*> center_manage_jmodmap;
+
+extern int tool_pack(char *pack_path,char *dir_path);
+extern int tool_unpack(char *pack_path,char *dir_path);
+extern int tool_cleardir(char *path);
+extern int tool_copydir(char *old_path,char *new_path);
+
+extern int center_judge_submit(int subid,int proid,int lang,char *set_data,size_t set_len);
+extern int center_judge_updatepro(std::vector<std::pair<int,int> > &pro_list);
diff --git a/judge/center_server.cpp b/judge/center_server.cpp
new file mode 100644
index 0000000..030e273
--- /dev/null
+++ b/judge/center_server.cpp
@@ -0,0 +1,198 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<unistd.h>
+#include<signal.h>
+#include<limits.h>
+#include<errno.h>
+#include<fcntl.h>
+#include<pthread.h>
+#include<semaphore.h>
+#include<libpq-fe.h>
+#include<sys/socket.h>
+#include<sys/epoll.h>
+#include<sys/eventfd.h>
+#include<netinet/in.h>
+#include<arpa/inet.h>
+#include<libpq-fe.h>
+#include<vector>
+#include<queue>
+
+#include"tpool.h"
+#include"center_server.h"
+
+server_epevdata::server_epevdata(int fd,int type,void *data){
+ this->fd = fd;
+ this->type = type;
+ this->data = data;
+}
+
+
+server_web_conn::server_web_conn(int fd){
+ this->fd = fd;
+ this->off = 0;
+ this->count = 0;
+}
+server_web_conn::~server_web_conn(){
+ epoll_ctl(server_epfd,EPOLL_CTL_DEL,fd,NULL);
+ close(fd);
+}
+int server_web_conn::readio(){
+ int ret;
+ char c;
+ int len;
+ int subid;
+ char *param;
+
+ while((ret = read(fd,&c,1)) > 0){
+ buf[off] = c;
+ off++;
+ if(c == '\0'){
+ count++;
+ if(count == 2){
+ break;
+ }
+ }
+ }
+
+ if(count == 2){
+ off = 0;
+ count = 0;
+
+ sscanf(buf,"%d",&subid);
+ param = buf + strlen(buf) + 1;
+ printf("%d %s\n",subid,param);
+
+ //test
+ if(subid == -1){
+ center_manage_updatedata();
+ }else{
+ center_manage_submit(subid,param);
+ }
+
+ //test
+
+ write(fd,"S",2);
+ }
+
+ return 0;
+}
+
+
+static int server_addepev(int fd,unsigned int flag,int type,void *data){
+ server_epevdata *epevdata;
+ epoll_event epev;
+
+ epevdata = new server_epevdata(fd,type,data);
+ epev.events = flag;
+ epev.data.ptr = epevdata;
+ epoll_ctl(server_epfd,EPOLL_CTL_ADD,fd,&epev);
+
+ return 0;
+}
+static int server_delepev(server_epevdata *epevdata){
+ epoll_ctl(server_epfd,EPOLL_CTL_DEL,epevdata->fd,NULL);
+ delete epevdata;
+ return 0;
+}
+int main(){
+ int ret;
+ int i;
+
+ int judge_sfd;
+ int web_sfd;
+ int cfd;
+ sockaddr_in saddr;
+ sockaddr_in caddr;
+ epoll_event epev;
+ epoll_event epevs[SERVER_EPOLL_MAXEVENT];
+ int nevs;
+
+ unsigned int ev_flag;
+ server_epevdata *epevdata;
+ server_web_conn *winfo;
+ tpool *tpinfo;
+
+ signal(SIGPIPE,SIG_IGN);
+ server_epfd = epoll_create1(0);
+ center_manage_init(&tpinfo);
+ server_addepev(tpinfo->fd,EPOLLIN | EPOLLET,SERVER_EPEV_TPOOL,tpinfo);
+ center_judge_init();
+
+ judge_sfd = socket(AF_INET,SOCK_STREAM | SOCK_NONBLOCK,6);
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = htons(SERVER_JUDGE_PORT);
+ //saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ //saddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ saddr.sin_addr.s_addr = inet_addr("10.8.0.2");
+ setsockopt(judge_sfd,SOL_SOCKET,SO_REUSEADDR,&saddr,sizeof(saddr));
+ bind(judge_sfd,(sockaddr*)&saddr,sizeof(saddr));
+
+ server_addepev(judge_sfd,EPOLLIN | EPOLLET,SERVER_EPEV_JUDGESERVER,NULL);
+ listen(judge_sfd,4096);
+
+ web_sfd = socket(AF_INET,SOCK_STREAM | SOCK_NONBLOCK,6);
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = htons(SERVER_WEB_PORT);
+ saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ //saddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ setsockopt(web_sfd,SOL_SOCKET,SO_REUSEADDR,&saddr,sizeof(saddr));
+ bind(web_sfd,(sockaddr*)&saddr,sizeof(saddr));
+
+ server_addepev(web_sfd,EPOLLIN | EPOLLET,SERVER_EPEV_WEBSERVER,NULL);
+ listen(web_sfd,4096);
+
+ while(true){
+ nevs = epoll_wait(server_epfd,epevs,SERVER_EPOLL_MAXEVENT,-1);
+ for(i = 0;i < nevs;i++){
+ ev_flag = epevs[i].events;
+ epevdata = (server_epevdata*)epevs[i].data.ptr;
+
+ if(epevdata->type == SERVER_EPEV_JUDGESERVER){
+ while(true){
+ ret = 0;
+ if((cfd = accept4(epevdata->fd,(sockaddr*)&caddr,(socklen_t*)&ret,SOCK_NONBLOCK)) == -1){
+ break;
+ }
+
+ server_addepev(cfd,EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET,SERVER_EPEV_JUDGECLIENT,center_judge_addconn(cfd));
+ }
+ }else if(epevdata->type == SERVER_EPEV_JUDGECLIENT){
+ center_judge_dispatch(ev_flag,epevdata->data);
+ if(ev_flag & EPOLLRDHUP){
+ server_delepev(epevdata);
+ }
+ }else if(epevdata->type == SERVER_EPEV_WEBSERVER){
+ printf("test\n");
+ while(true){
+ ret = 0;
+ if((cfd = accept4(epevdata->fd,(sockaddr*)&caddr,(socklen_t*)&ret,SOCK_NONBLOCK)) == -1){
+ break;
+ }
+
+ server_addepev(cfd,EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET,SERVER_EPEV_WEBCLIENT,new server_web_conn(cfd));
+ }
+ }else if(epevdata->type == SERVER_EPEV_WEBCLIENT){
+ winfo = (server_web_conn*)epevdata->data;
+ if(ev_flag & EPOLLIN){
+ winfo->readio();
+ }
+ if(ev_flag & EPOLLRDHUP){
+ delete winfo;
+ delete (server_epevdata*)epev.data.ptr;
+ }
+ }else if(epevdata->type == SERVER_EPEV_TPOOL){
+ tpinfo = (tpool*)epevdata->data;
+ if(ev_flag & EPOLLIN){
+ tpinfo->done();
+ }
+ }
+ }
+ }
+
+ close(judge_sfd);
+ close(server_epfd);
+ close(web_sfd);
+
+ return 0;
+}
diff --git a/judge/center_server.h b/judge/center_server.h
new file mode 100644
index 0000000..039e84b
--- /dev/null
+++ b/judge/center_server.h
@@ -0,0 +1,45 @@
+#define SERVER_JUDGE_PORT 2573
+#define SERVER_WEB_PORT 2501
+#define SERVER_EPOLL_MAXEVENT 4096
+
+#define SERVER_EPEV_JUDGESERVER 0
+#define SERVER_EPEV_JUDGECLIENT 1
+#define SERVER_EPEV_WEBSERVER 2
+#define SERVER_EPEV_WEBCLIENT 3
+#define SERVER_EPEV_TPOOL 4
+class server_epevdata{
+public:
+ int fd;
+ int type;
+ void *data;
+
+ server_epevdata(int fd,int type,void *data);
+};
+
+class server_web_conn{
+private:
+ int fd;
+ char buf[65536];
+ int off;
+ int count;
+
+public:
+ server_web_conn(int fd);
+ ~server_web_conn();
+ int readio();
+};
+
+static int server_addepev(int fd,unsigned int flag,int type,void *data);
+static int server_delepev(server_epevdata *epevdata);
+static int server_epfd;
+
+extern int center_manage_init(tpool **tpinfo);
+extern int center_manage_updatedata();
+extern int center_manage_submit(int subid,char *param);
+
+extern int center_judge_init();
+extern void* center_judge_addconn(int fd);
+extern int center_judge_dispatch(int ev_flag,void *data);
+
+extern int pack_pack(char *pack_path,char *dir_path);
+extern int pack_unpack(char *pack_path,char *target_path);
diff --git a/judge/event_exec.cpp b/judge/event_exec.cpp
new file mode 100644
index 0000000..af258c0
--- /dev/null
+++ b/judge/event_exec.cpp
@@ -0,0 +1,89 @@
+#include "event_exec.h"
+
+#define EVENT_BUFLEN 1005
+#define EVENT_URL "http://localhost/toj/php/event.php"
+
+struct event_handle
+{
+ int init, plen, blen;
+ char *post, *buf;
+ pthread_mutex_t mutex;
+ CURL *handle;
+};
+
+static struct event_handle conn;
+
+size_t event_write_cb(void *in, size_t siz, size_t nb, void *buf)
+{
+ int len;
+ len = siz*nb+1;
+ if(len > conn.blen)
+ {
+ len = conn.blen-1;
+ }
+ memcpy(buf, in, len);
+ ((char*)buf)[len] = 0;
+ return siz*nb;
+}
+
+int event_init()
+{
+ if(conn.init)
+ {
+ return 0;
+ }
+ conn.plen = conn.blen = EVENT_BUFLEN;
+ conn.post = (char*)malloc(EVENT_BUFLEN);
+ conn.buf = (char*)malloc(EVENT_BUFLEN);
+ curl_global_init(CURL_GLOBAL_ALL);
+ conn.handle = curl_easy_init();
+ curl_easy_setopt(conn.handle, CURLOPT_URL, EVENT_URL);
+ curl_easy_setopt(conn.handle, CURLOPT_WRITEFUNCTION, event_write_cb);
+ curl_easy_setopt(conn.handle, CURLOPT_WRITEDATA, conn.buf);
+ pthread_mutex_init(&conn.mutex, NULL);
+ conn.init = 1;
+ return 1;
+}
+
+int event_exec(const char *fname, const char *name, const char *arg)
+{
+ int res, len;
+ char *t;
+ event_init();
+ if(pthread_mutex_lock(&conn.mutex) == 0)
+ {
+ len = 0;
+ len += strlen(fname)+6;
+ len += strlen(name)+6;
+ len += strlen(arg)+6;
+ if(len > conn.plen)
+ {
+ t = (char*)malloc(len);
+ if(!t)
+ {
+ pthread_mutex_unlock(&conn.mutex);
+ return 0;
+ }
+ free(conn.post);
+ conn.post = t;
+ conn.plen = len;
+ }
+ sprintf(conn.post, "fname=%s&name=%s&arg=%s", fname, name, arg);
+ curl_easy_setopt(conn.handle, CURLOPT_POSTFIELDS, conn.post);
+ res = curl_easy_perform(conn.handle);
+ if(res)
+ {
+ pthread_mutex_unlock(&conn.mutex);
+ return 0;
+ }
+ fprintf(stderr, "%s\n", conn.buf);
+ if(!strcmp(conn.buf, "true"))
+ {
+ pthread_mutex_unlock(&conn.mutex);
+ return 1;
+ }
+
+ pthread_mutex_unlock(&conn.mutex);
+ }
+ return 0;
+}
diff --git a/judge/event_exec.h b/judge/event_exec.h
new file mode 100644
index 0000000..aec1acb
--- /dev/null
+++ b/judge/event_exec.h
@@ -0,0 +1,12 @@
+#ifndef EVENT_EXEC
+#define EVENT_EXEC
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <curl/curl.h>
+#include <pthread.h>
+
+int event_exec(const char *fname, const char *name, const char *arg);
+
+#endif
diff --git a/judge/jmod_test.h b/judge/jmod_test.h
new file mode 100644
index 0000000..844f5c8
--- /dev/null
+++ b/judge/jmod_test.h
@@ -0,0 +1,17 @@
+#define LINE_ERRMSG_MAXSIZE 4096
+
+typedef int (*check_init_fn)(int judgk_modfd,char *data_path,char *run_path);
+typedef int (*check_run_fn)(int &status,char *err_msg);
+typedef int (*check_stop_fn)();
+
+struct line_set_data{
+ int id;
+};
+struct line_result_data{
+ int id;
+ int status;
+ double score;
+ unsigned long runtime;
+ unsigned long memory;
+ char err_msg[LINE_ERRMSG_MAXSIZE];
+};
diff --git a/judge/jmod_test_check.cpp b/judge/jmod_test_check.cpp
new file mode 100644
index 0000000..984473b
--- /dev/null
+++ b/judge/jmod_test_check.cpp
@@ -0,0 +1,109 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<limits.h>
+#include<unistd.h>
+#include<fcntl.h>
+#include<errno.h>
+
+#include<judge_def.h>
+#include"judgm_lib.h"
+#include"jmod_test.h"
+#include"jmod_test_check.h"
+
+static int ansfd;
+static judgm_hyperio *hyperio;
+static int tty_idx;
+
+int p[2];
+
+DLL_PUBLIC int init(int judgk_modfd,char *datapath,char *runpath){
+ char tpath[PATH_MAX + 1];
+ char dstpath[PATH_MAX + 1];
+
+ pipe(p);
+
+ snprintf(tpath,sizeof(tpath),"%s/in",datapath);
+ snprintf(dstpath,sizeof(dstpath),"%s/in",runpath);
+ if(link(tpath,dstpath)){
+ return -1;
+ }
+ snprintf(tpath,sizeof(tpath),"%s/ans",datapath);
+ if((ansfd = open(tpath,O_RDONLY)) == -1){
+ return -1;
+ }
+
+ //hyperio = new judgm_hyperio(judgk_modfd);
+ //tty_idx = hyperio->tty_idx;
+
+ return 0;
+}
+DLL_PUBLIC int run(int &status,char *err_msg){
+ int ret;
+
+ char *inbuf;
+ char *ansbuf;
+
+ status = JUDGE_AC;
+ inbuf = new char[65536];
+ ansbuf = new char[65536];
+
+ /*while((ret = read(ansfd,ansbuf,65536)) > 0){
+ if(hyperio->compare(ansbuf,ret)){
+ status = JUDGE_WA;
+ break;
+ }
+ }
+ if(status == JUDGE_AC && hyperio->wait() > 0){
+ status = JUDGE_WA;
+ }
+
+ delete inbuf;
+ delete ansbuf;
+ close(ansfd);
+ delete hyperio;*/
+
+ close(p[1]);
+ int c_read=-1,pre_status=status;
+ while((ret = read(p[0],inbuf,65536)) > 0){
+ if((c_read=read(ansfd,ansbuf,ret)) != ret){
+ status = JUDGE_WA;
+ break;
+ }
+ if(memcmp(ansbuf,inbuf,ret)){
+ status = JUDGE_WA;
+ break;
+ }
+ }
+// if(c_read - ret == 1 && ansbuf[c_read-1]=='\n'){
+// status = pre_status;
+// }
+
+ if(status == JUDGE_AC && ((c_read = read(ansfd,ansbuf,1)) > 1 || c_read == 1 && ansbuf[0]!='\n')){
+ status = JUDGE_WA;
+ }
+
+ return 0;
+}
+DLL_PUBLIC int proc(){
+ int infd;
+ int outfd;
+
+ if((infd = open("in",O_RDONLY)) == -1){
+ return -1;
+ }
+ /*if((outfd = judgm_hyperio::get_ttyfd(tty_idx)) == -1){
+ return -1;
+ }*/
+
+ close(p[0]);
+ outfd = p[1];
+ dup2(infd,0);
+ dup2(outfd,1);
+ dup2(outfd,2);
+
+ return 0;
+}
+DLL_PUBLIC int stop(){
+ return 0;
+}
diff --git a/judge/jmod_test_check.h b/judge/jmod_test_check.h
new file mode 100644
index 0000000..20a6286
--- /dev/null
+++ b/judge/jmod_test_check.h
@@ -0,0 +1,4 @@
+DLL_PUBLIC int init(int judgk_modfd,char *datapath,char *runpath);
+DLL_PUBLIC int run(int &status,char *err_msg);
+DLL_PUBLIC int proc();
+DLL_PUBLIC int stop();
diff --git a/judge/jmod_test_line.cpp b/judge/jmod_test_line.cpp
new file mode 100644
index 0000000..33a32b9
--- /dev/null
+++ b/judge/jmod_test_line.cpp
@@ -0,0 +1,190 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<limits.h>
+#include<dlfcn.h>
+#include<pthread.h>
+#include<json/json.h>
+
+#include<judge_def.h>
+#include"judgm_lib.h"
+#include"judgm_line.h"
+#include"jmod_test.h"
+#include"jmod_test_line.h"
+
+static int line_load_setfile(FILE *set_file,int id,int &timelimit,int &memlimit,double &score){
+ int ret;
+
+ json_object *jso;
+ char buf[JUDGE_SET_FILEMAX];
+
+ fread(buf,1,sizeof(buf),set_file);
+ jso = json_tokener_parse(buf);
+
+ timelimit = json_object_get_int(json_object_object_get(jso,"timelimit"));
+ memlimit = json_object_get_int(json_object_object_get(jso,"memlimit"));
+ score = json_object_get_double(json_object_array_get_idx(json_object_object_get(jso,"score"),id - 1));
+
+ json_object_put(jso);
+ return 0;
+}
+static void line_sigaction(int sig_num,siginfo_t *sig_info,void *context){
+ if(sig_info->si_pid == line_proc->pid && line_proc->status == JUDGE_RUN){
+ if(!line_proc->proc_wait(false)){
+ line_chk_stop_fn();
+ }
+ }
+}
+static int line_sig_set(){
+ struct sigaction sig;
+
+ sig.sa_sigaction = line_sigaction;
+ sigemptyset(&sig.sa_mask);
+ sig.sa_flags = SA_SIGINFO | SA_RESTART;
+ if(sigaction(SIGCHLD,&sig,NULL)){
+ return -1;
+ }
+
+ return 0;
+}
+static int line_sig_restore(){
+ struct sigaction sig;
+
+ sig.sa_handler = SIG_DFL;
+ sigemptyset(&sig.sa_mask);
+ sig.sa_flags = 0;
+ if(sigaction(SIGCHLD,&sig,NULL)){
+ return -1;
+ }
+
+ return 0;
+}
+static int line_sig_block(){
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask,SIGCHLD);
+ if(pthread_sigmask(SIG_BLOCK,&mask,NULL)){
+ return -1;
+ }
+
+ return 0;
+}
+static int line_sig_unblock(){
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask,SIGCHLD);
+ if(pthread_sigmask(SIG_UNBLOCK,&mask,NULL)){
+ return -1;
+ }
+
+ return 0;
+}
+static int line_sig_wait(){
+ sigset_t mask;
+ int num;
+
+ sigfillset(&mask);
+ sigdelset(&mask,SIGKILL);
+ sigdelset(&mask,SIGTERM);
+ sigdelset(&mask,SIGINT);
+ sigdelset(&mask,SIGCHLD);
+ sigsuspend(&mask);
+
+ return 0;
+}
+DLL_PUBLIC int run(judgm_line_info *info){
+ int i;
+
+ line_result_data *res_data;
+
+ int set_timelimit;
+ int set_memlimit;
+ double set_score;
+ line_set_data *set_data;
+
+ char main_path[PATH_MAX + 1];
+ char exe_path[PATH_MAX + 1];
+
+ check_init_fn chk_init_fn;
+ check_run_fn chk_run_fn;
+ judgm_proc_check_fn chk_proc_fn;
+
+ char data_path[PATH_MAX + 1];
+ int chk_status;
+
+ set_data = (line_set_data*)info->set_data;
+
+ res_data = (line_result_data*)info->res_data;
+ info->res_len = sizeof(line_result_data);
+
+ res_data->id = set_data->id;
+ res_data->status = JUDGE_ERR;
+ res_data->score = 0;
+ res_data->runtime = 0;
+ res_data->memory = 0;
+ res_data->err_msg[0] = '\0';
+
+ if(line_load_setfile(info->set_file,set_data->id,set_timelimit,set_memlimit,set_score)){
+ return -1;
+ }
+
+ snprintf(main_path,sizeof(main_path),"%s/main.cpp",info->code_path);
+ snprintf(exe_path,sizeof(exe_path),"%s/test",info->run_path);
+ if(judgm_compile(info->subid,main_path,exe_path,info->lang,false,res_data->err_msg,LINE_ERRMSG_MAXSIZE)){
+ res_data->status = JUDGE_CE;
+ return -1;
+ }
+
+ chk_init_fn = (check_init_fn)dlsym(info->check_dll,"init");
+ chk_run_fn = (check_run_fn)dlsym(info->check_dll,"run");
+ chk_proc_fn = (judgm_proc_check_fn)dlsym(info->check_dll,"proc");
+ line_chk_stop_fn = (check_stop_fn)dlsym(info->check_dll,"stop");
+ line_proc = new judgm_proc(info->judgk_modfd,info->run_path,exe_path,set_timelimit,(set_timelimit * 10 + 5000),set_memlimit,chk_proc_fn);
+
+ snprintf(data_path,sizeof(data_path),"%s/private/%d",info->pro_path,set_data->id);
+ if(chk_init_fn(info->judgk_modfd,data_path,info->run_path)){
+ delete line_proc;
+ return -1;
+ }
+ if(line_sig_set()){
+ delete line_proc;
+ return -1;
+ }
+
+ if(line_proc->proc_run()){
+ delete line_proc;
+ return -1;
+ }
+ chk_run_fn(chk_status,res_data->err_msg);
+
+ line_sig_block();
+ if(line_proc->status == JUDGE_RUN){
+ line_proc->proc_kill();
+ line_sig_wait();
+ }
+ line_sig_unblock();
+
+ printf("check status %d proc status %d\n",chk_status,line_proc->status);
+
+ if(line_sig_restore()){
+ delete line_proc;
+ return -1;
+ }
+
+ if(line_proc->status != JUDGE_AC){
+ res_data->status = line_proc->status;
+ }else{
+ res_data->status = chk_status;
+ }
+ if(res_data->status == JUDGE_AC){
+ res_data->score = set_score;
+ }else{
+ res_data->score = 0;
+ }
+ res_data->runtime = line_proc->runtime;
+ res_data->memory = line_proc->memory;
+
+ delete line_proc;
+ return 0;
+}
diff --git a/judge/jmod_test_line.h b/judge/jmod_test_line.h
new file mode 100644
index 0000000..c09a503
--- /dev/null
+++ b/judge/jmod_test_line.h
@@ -0,0 +1,11 @@
+static int line_load_setfile(FILE *set_file,int test_id,int &timelimit,int &memlimit,double &score);
+static int line_sig_set();
+static int line_sig_restore();
+static int line_sig_block();
+static int line_sig_unblock();
+static int line_sig_wait();
+
+static judgm_proc *line_proc;
+static check_stop_fn line_chk_stop_fn;
+
+DLL_PUBLIC int run(judgm_line_info *info);
diff --git a/judge/jmod_test_manage.cpp b/judge/jmod_test_manage.cpp
new file mode 100644
index 0000000..b020574
--- /dev/null
+++ b/judge/jmod_test_manage.cpp
@@ -0,0 +1,96 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<limits.h>
+#include<dlfcn.h>
+#include<json/json.h>
+
+#include<judge_def.h>
+#include"judgm_lib.h"
+#include"judgm_manage.h"
+#include"jmod_test.h"
+#include"jmod_test_manage.h"
+
+static void __attribute__ ((constructor)) manage_init(){
+ manage_queuesubmit_fn = (judgm_manage_queuesubmit_fn)dlsym(dlopen(NULL,RTLD_NOW),"center_manage_queuesubmit");
+}
+static int manage_load_setfile(FILE *set_file,int &count){
+ int ret;
+
+ json_object *jso;
+ char buf[JUDGE_SET_FILEMAX];
+
+ fread(buf,1,sizeof(buf),set_file);
+ jso = json_tokener_parse(buf);
+
+ count = json_object_get_int(json_object_object_get(jso,"count"));
+
+ json_object_put(jso);
+ return 0;
+}
+
+DLL_PUBLIC int submit(judgm_manage_info *info,FILE *set_file){
+ int i;
+
+ int count;
+ manage_result_info *res_info;
+ line_set_data set_data;
+
+ manage_load_setfile(set_file,count);
+
+ res_info = new manage_result_info(count);
+ info->private_data = res_info;
+
+ for(i = 0;i < count;i++){
+ set_data.id = i + 1;
+ manage_queuesubmit_fn(info->subid,info->proid,info->lang,(char*)&set_data,sizeof(line_set_data));
+ }
+
+ return 0;
+}
+DLL_PUBLIC int result(judgm_manage_info *info,line_result_data *res_data){
+ manage_result_info *res_info;
+ json_object *jso_item;
+ char tpath[PATH_MAX + 1];
+
+ res_info = (manage_result_info*)info->private_data;
+ res_info->count++;
+
+ if(res_data->status > res_info->result){
+ res_info->result = res_data->status;
+ }
+ res_info->totalscore += res_data->score;
+ res_info->totalruntime += res_data->runtime;
+ if(res_data->memory > res_info->maxmemory){
+ res_info->maxmemory = res_data->memory;
+ }
+
+ jso_item = json_object_new_object();
+ json_object_object_add(jso_item,"status",json_object_new_int(res_data->status));
+ json_object_object_add(jso_item,"score",json_object_new_double(res_data->score));
+ json_object_object_add(jso_item,"runtime",json_object_new_int64(res_data->runtime));
+ json_object_object_add(jso_item,"memory",json_object_new_int64(res_data->memory / 1024UL));
+ if(strlen(res_data->err_msg) > 0){
+ printf(" strlen %d\n",strlen(res_data->err_msg));
+ json_object_object_add(jso_item,"errmsg",json_object_new_string(res_data->err_msg));
+ }
+ json_object_array_put_idx(res_info->jso_resarray,res_data->id - 1,jso_item);
+
+ printf("jmod count %d %d\n",res_info->count,res_info->allcount);
+
+ if(res_info->count == res_info->allcount){
+ snprintf(tpath,sizeof(tpath),"%s/result",info->res_path);
+ json_object_to_file_ext(tpath,res_info->jso_res,JSON_C_TO_STRING_PLAIN);
+
+ info->result = res_info->result;
+ info->score = res_info->totalscore;
+ info->runtime = res_info->totalruntime;
+ info->memory = res_info->maxmemory;
+
+ delete res_info;
+ return 1;
+ }
+ return 0;
+}
+
+
diff --git a/judge/jmod_test_manage.h b/judge/jmod_test_manage.h
new file mode 100644
index 0000000..b0244e3
--- /dev/null
+++ b/judge/jmod_test_manage.h
@@ -0,0 +1,35 @@
+class manage_result_info{
+public:
+ int allcount;
+ int count;
+ int result;
+ double totalscore;
+ unsigned long totalruntime;
+ unsigned long maxmemory;
+ json_object *jso_res;
+ json_object *jso_resarray;
+
+ manage_result_info(int allcount){
+ this->allcount = allcount;
+ this->count = 0;
+ this->result = JUDGE_AC;
+ this->totalscore = 0;
+ this->totalruntime = 0;
+ this->maxmemory = 0;
+
+ this->jso_res = json_object_new_object();
+ this->jso_resarray = json_object_new_array();
+ json_object_object_add(this->jso_res,"result",this->jso_resarray);
+ }
+ ~manage_result_info(){
+ json_object_put(jso_res);
+ }
+};
+
+DLL_PUBLIC int submit(judgm_manage_info *info,FILE *set_file);
+DLL_PUBLIC int result(judgm_manage_info *info,line_result_data *res_data);
+
+static void __attribute__ ((constructor)) manage_init();
+static int manage_load_setfile(FILE *setfile,int &count);
+
+static judgm_manage_queuesubmit_fn manage_queuesubmit_fn;
diff --git a/judge/judge.h b/judge/judge.h
new file mode 100644
index 0000000..5183942
--- /dev/null
+++ b/judge/judge.h
@@ -0,0 +1,44 @@
+#ifndef JUDGE_H
+#define JUDGE_H
+
+#define JUDGE_THREAD_MAX 16
+#define JUDGE_THREAD_JUDGEMAX 2
+
+#define JUDGE_CACHESTATE_READY 0
+#define JUDGE_CACHESTATE_UPDATE 1
+
+class judge_pro_info{
+public:
+ int proid;
+ int cacheid;
+ int ref_count;
+
+ int state;
+ int update_cacheid;
+
+ judge_pro_info(int proid,int cacheid){
+ this->proid = proid;
+ this->cacheid = cacheid;
+ this->ref_count = 0;
+
+ this->state = JUDGE_CACHESTATE_READY;
+ this->update_cacheid = 0;
+ }
+};
+
+class judge_submit_info{
+public:
+ int subid;
+ judge_pro_info *pro_info;
+ int lang;
+ char *set_data;
+
+ judge_submit_info(int subid,judge_pro_info *pro_info,int lang,char *set_data){
+ this->subid = subid;
+ this->pro_info = pro_info;
+ this->lang = lang;
+ this->set_data = set_data;
+ }
+};
+
+#endif
diff --git a/judge/judge_manage.cpp b/judge/judge_manage.cpp
new file mode 100644
index 0000000..32181bc
--- /dev/null
+++ b/judge/judge_manage.cpp
@@ -0,0 +1,371 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<unistd.h>
+#include<limits.h>
+#include<dirent.h>
+#include<dlfcn.h>
+#include<sys/types.h>
+#include<sys/stat.h>
+#include<sys/mman.h>
+#include<map>
+
+#include"tpool.h"
+#include"judge_def.h"
+#include"judge.h"
+#include"judgm_line.h"
+#include"judgm_lib.h"
+#include"judge_manage.h"
+
+int judge_manage_init(){
+ int i;
+
+ manage_tp = new tpool(JUDGE_THREAD_MAX);
+ judge_server_addtpool(manage_tp);
+ manage_tp->start();
+
+ manage_judgk_modfd = open("/dev/judgk",O_RDWR);
+ for(i = 0;i < JUDGE_THREAD_JUDGEMAX;i++){
+ manage_judgepool[i] = new manage_judgeth_info(i);
+ }
+ manage_updatepro_thfn = new tpool_static_fn(manage_updatepro_th);
+ manage_updatepro_cbfn = new tpool_static_fn(manage_updatepro_cb);
+ manage_unpackcode_thfn = new tpool_static_fn(manage_unpackcode_th);
+ manage_unpackcode_cbfn = new tpool_static_fn(manage_unpackcode_cb);
+ manage_judge_thfn = new tpool_static_fn(manage_judge_th);
+ manage_judge_cbfn = new tpool_static_fn(manage_judge_cb);
+
+ judge_manage_updatedata();
+ return 0;
+}
+int judge_manage_updatedata(){
+ DIR *dirp;
+ char *buf;
+ dirent *entry;
+ int proid;
+ int cacheid;
+ judge_pro_info *pro_info;
+
+ if((dirp = opendir("tmp/pro")) == NULL){
+ return -1;
+ }
+ buf = new char[sizeof(dirent) + NAME_MAX + 1];
+
+ while(true){
+ readdir_r(dirp,(dirent*)buf,&entry);
+ if(entry == NULL){
+ break;
+ }
+ if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0){
+ continue;
+ }
+
+ if(entry->d_type == DT_DIR){
+ sscanf(entry->d_name,"%d_%d",&proid,&cacheid);
+ pro_info = new judge_pro_info(proid,cacheid);
+ judge_manage_getpro(pro_info);
+ judge_manage_promap.insert(std::make_pair(proid,pro_info));
+ }
+ }
+
+ delete(buf);
+ closedir(dirp);
+
+ return 0;
+}
+
+judge_pro_info* judge_manage_getprobyid(int proid){
+ std::map<int,judge_pro_info*>::iterator pro_it;
+ judge_pro_info *pro_info;
+
+ if((pro_it = judge_manage_promap.find(proid)) == judge_manage_promap.end()){
+ return NULL;
+ }
+ pro_info = pro_it->second;
+
+ if(judge_manage_getpro(pro_info)){
+ return NULL;
+ }
+
+ return pro_info;
+}
+int judge_manage_getpro(judge_pro_info *pro_info){
+ pro_info->ref_count++;
+ return 0;
+}
+int judge_manage_putpro(judge_pro_info *pro_info){
+ std::map<int,judge_pro_info*> pro_it;
+ char tpath[PATH_MAX + 1];
+ char src_path[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);
+
+ delete pro_info;
+ }
+ return 0;
+}
+int judge_manage_updatepro(int proid,int cacheid,bool check_flag,judge_pro_info **update_pro_info){ //If check_flag = true, just check
+ int ret;
+
+ std::map<int,judge_pro_info*>::iterator pro_it;
+ judge_pro_info *old_pro_info;
+
+ if((pro_it = judge_manage_promap.find(proid)) == judge_manage_promap.end()){
+ if(check_flag == true){
+ return 0;
+ }
+ }else{
+ old_pro_info = pro_it->second;
+
+ if(old_pro_info->state == JUDGE_CACHESTATE_READY && cacheid == old_pro_info->cacheid){
+ return 1;
+ }
+ if(old_pro_info->state == JUDGE_CACHESTATE_UPDATE && (cacheid <= old_pro_info->cacheid || cacheid <= old_pro_info->update_cacheid)){
+ return -1;
+ }
+
+ if(check_flag == true){
+ return 0;
+ }
+
+ old_pro_info->update_cacheid = cacheid;
+ old_pro_info->state = JUDGE_CACHESTATE_UPDATE;
+ }
+
+ *update_pro_info = new judge_pro_info(proid,cacheid);
+ judge_manage_getpro(*update_pro_info);
+
+ return 0;
+}
+int judge_manage_done_updatepro(judge_pro_info *pro_info){
+ manage_tp->add(manage_updatepro_thfn,pro_info,manage_updatepro_cbfn,pro_info);
+ return 0;
+}
+static void manage_updatepro_th(void *data){
+ judge_pro_info *pro_info;
+ int proid;
+ int cacheid;
+ char pack_path[PATH_MAX + 1];
+ char dir_path[PATH_MAX + 1];
+ char tpath[PATH_MAX + 1];
+ FILE *f;
+
+ pro_info = (judge_pro_info*)data;
+
+ snprintf(pack_path,sizeof(pack_path),"tmp/propack/%d_%d.tar.bz2",pro_info->proid,pro_info->cacheid);
+ snprintf(dir_path,sizeof(dir_path),"tmp/pro/%d_%d",pro_info->proid,pro_info->cacheid);
+ mkdir(dir_path,0755);
+ tool_cleardir(dir_path);
+ tool_unpack(pack_path,dir_path);
+ //unlink(pack_path);
+
+ snprintf(tpath,sizeof(tpath),"tmp/pro/%d_%d/cacheinfo",pro_info->proid,pro_info->cacheid);
+ f = fopen(tpath,"w");
+ fprintf(f,"%d",pro_info->cacheid);
+ fclose(f);
+}
+static void manage_updatepro_cb(void *data){
+ judge_pro_info *old_pro_info;
+ judge_pro_info *update_pro_info;
+ std::pair<std::map<int,judge_pro_info*>::iterator,bool> ins_ret;
+ std::vector<std::pair<int,int> > pro_list;
+
+ update_pro_info = (judge_pro_info*)data;
+
+ ins_ret = judge_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){
+ judge_manage_putpro(update_pro_info);
+ return;
+ }
+
+ judge_manage_putpro(ins_ret.first->second);
+ ins_ret.first->second = update_pro_info;
+ }
+
+ pro_list.push_back(std::make_pair(update_pro_info->proid,update_pro_info->cacheid));
+ judge_server_setpro(pro_list);
+}
+
+
+int judge_manage_submit(int subid,int proid,int lang,char *set_data,int set_len){
+ judge_pro_info *pro_info;
+ judge_submit_info *sub_info;
+
+ char tpath[PATH_MAX + 1];
+ struct stat st;
+
+ pro_info = judge_manage_getprobyid(proid);
+ sub_info = new judge_submit_info(subid,pro_info,lang,set_data,set_len);
+
+ if(manage_submap.find(subid) == manage_submap.end()){
+ snprintf(tpath,sizeof(tpath),"tmp/code/%d",subid);
+ if(!stat(tpath,&st)){
+ manage_queuejudge(sub_info);
+ }else{
+ judge_server_reqcode(subid);
+ manage_submap.insert(std::make_pair(subid,sub_info));
+ }
+ }else{
+ manage_submap.insert(std::make_pair(subid,sub_info));
+ }
+
+ return 0;
+}
+int judge_manage_done_code(int subid){
+ manage_tp->add(manage_unpackcode_thfn,(void*)((long)subid),manage_unpackcode_cbfn,(void*)((long)subid));
+ return 0;
+}
+static void manage_unpackcode_th(void *data){
+ int subid;
+ char pack_path[PATH_MAX + 1];
+ char dir_path[PATH_MAX + 1];
+ char tpath[PATH_MAX + 1];
+ FILE *f;
+
+ subid = (int)((long)data);
+
+ snprintf(pack_path,sizeof(pack_path),"tmp/codepack/%d.tar.bz2",subid);
+ snprintf(dir_path,sizeof(dir_path),"tmp/code/%d",subid);
+ mkdir(dir_path,0755);
+ tool_cleardir(dir_path);
+ tool_unpack(pack_path,dir_path);
+}
+static void manage_unpackcode_cb(void *data){
+ int subid;
+ std::multimap<int,judge_submit_info*>::iterator sub_it;
+ judge_submit_info *sub_info;
+
+ subid = (int)((long)data);
+
+ while((sub_it = manage_submap.find(subid)) != manage_submap.end()){
+ sub_info = sub_it->second;
+ manage_queuejudge(sub_info);
+ manage_submap.erase(sub_it);
+ }
+}
+static int manage_queuejudge(judge_submit_info *sub_info){
+ int i;
+
+ printf("queue judge %d %d\n",sub_info->subid,sub_info->pro_info->proid);
+ for(i = 0;i < 16;i++){
+ if(manage_judgepool[i]->use_flag == false){
+ manage_judgepool[i]->use_flag = true;
+ manage_judgepool[i]->sub_info = sub_info;
+ manage_tp->add(manage_judge_thfn,manage_judgepool[i],manage_judge_cbfn,manage_judgepool[i]);
+ break;
+ }
+ }
+
+ return 0;
+}
+static void manage_judge_th(void *data){
+ manage_judgeth_info *th_info;
+ judge_submit_info *sub_info;
+ judge_pro_info *pro_info;
+ char pro_path[PATH_MAX + 1];
+ char code_path[PATH_MAX + 1];
+ char *set_data;
+
+ th_info = (manage_judgeth_info*)data;
+ sub_info = th_info->sub_info;
+ pro_info = sub_info->pro_info;
+
+ snprintf(pro_path,sizeof(pro_path),"tmp/pro/%d_%d",pro_info->proid,pro_info->cacheid);
+ snprintf(code_path,sizeof(code_path),"tmp/code/%d",sub_info->subid);
+ manage_judge(sub_info->subid,pro_path,code_path,th_info->run_path,sub_info->lang,sub_info->set_data,th_info->res_data,th_info->res_len);
+}
+static void manage_judge_cb(void *data){
+ manage_judgeth_info *th_info;
+ judge_submit_info *sub_info;
+ std::vector<std::pair<int,int> > pro_list;
+
+ th_info = (manage_judgeth_info*)data;
+ sub_info = th_info->sub_info;
+
+ judge_server_result(sub_info->subid,th_info->res_data,th_info->res_len);
+ judge_manage_putpro(sub_info->pro_info);
+
+ th_info->use_flag = false;
+ th_info->sub_info = NULL;
+ delete sub_info;
+}
+static int manage_judge(int subid,char *pro_path,char *code_path,char *run_path,int lang,char *set_data,char *res_data,size_t &res_len){
+ judgm_line_info *line_info;
+ int pid;
+
+ char tpath[PATH_MAX + 1];
+ FILE *set_file;
+ char cwd_path[PATH_MAX + 1];
+ char jmod_name[NAME_MAX + 1];
+ char line_path[PATH_MAX + 1];
+ char check_name[NAME_MAX + 1];
+ char check_path[PATH_MAX + 1];
+ char lchr;
+ char tchr;
+
+ void *line_dll;
+ void *check_dll;
+ judgm_line_run_fn run_fn;
+
+ snprintf(tpath,sizeof(tpath),"%s/setting",pro_path);
+ set_file = fopen(tpath,"r");
+
+ getcwd(cwd_path,sizeof(cwd_path));
+ fscanf(set_file,"%s",jmod_name);
+ snprintf(line_path,sizeof(line_path),"%s/tmp/jmod/%s/%s_line.so",cwd_path,jmod_name,jmod_name);
+ fscanf(set_file,"%s",check_name);
+ if(check_name[0] == '/'){
+ snprintf(check_path,sizeof(check_path),"%s/%s/private%s.so",cwd_path,pro_path,check_name);
+ }else{
+ snprintf(check_path,sizeof(check_path),"%s/tmp/jmod/%s/%s.so",cwd_path,jmod_name,check_name);
+ }
+
+ lchr = '\n';
+ while((tchr = fgetc(set_file)) != EOF){
+ if(lchr == '\n' && tchr == '='){
+ while(fgetc(set_file) != '\n');
+ break;
+ }
+ lchr = tchr;
+ }
+
+ line_dll = dlopen(line_path,RTLD_NOW);
+ check_dll = dlopen(check_path,RTLD_NOW);
+
+ line_info = (judgm_line_info*)mmap(NULL,sizeof(struct judgm_line_info),PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS,-1,0);
+ line_info->subid = subid;
+ line_info->pro_path = pro_path;
+ line_info->code_path = code_path;
+ line_info->run_path = run_path;
+
+ line_info->judgk_modfd = manage_judgk_modfd;
+ line_info->line_dll = line_dll;
+ line_info->check_dll = check_dll;
+
+ line_info->lang = lang;
+ line_info->set_file = set_file;
+ line_info->set_data = set_data;
+
+ tool_cleardir(line_info->run_path);
+
+ run_fn = (judgm_line_run_fn)dlsym(line_dll,"run");
+ if((pid = fork()) == 0){
+ run_fn(line_info);
+ exit(0);
+ }
+ waitpid(pid,NULL,0);
+
+ memcpy(res_data,line_info->res_data,line_info->res_len);
+ res_len = line_info->res_len;
+
+ munmap(line_info,sizeof(judgm_line_info));
+ fclose(set_file);
+ return 0;
+}
diff --git a/judge/judge_manage.h b/judge/judge_manage.h
new file mode 100644
index 0000000..594ea71
--- /dev/null
+++ b/judge/judge_manage.h
@@ -0,0 +1,60 @@
+class manage_judgeth_info{
+public:
+ bool use_flag;
+ int thid;
+ char run_path[PATH_MAX + 1];
+ judge_submit_info *sub_info;
+ char res_data[JUDGE_RES_DATAMAX];
+ size_t res_len;
+
+ manage_judgeth_info(int thid){
+ this->use_flag = false;
+ this->thid = thid;
+ snprintf(this->run_path,sizeof(this->run_path),"tmp/run/%d",thid);
+ mkdir(this->run_path,0775);
+ this->sub_info = NULL;
+ this->res_len = 0;
+ }
+};
+
+static void manage_updatepro_th(void *data);
+static void manage_updatepro_cb(void *data);
+static void manage_unpackcode_th(void *data);
+static void manage_unpackcode_cb(void *data);
+static void manage_judge_th(void *data);
+static void manage_judge_cb(void *data);
+static int manage_queuejudge(judge_submit_info *sub_info);
+static int manage_judge(int subid,char *pro_path,char *code_path,char *run_path,int lang,char *set_data,char *res_data,size_t &res_len);
+
+static tpool *manage_tp;
+static int manage_judgk_modfd;
+static manage_judgeth_info *manage_judgepool[16];
+static tpool_static_fn *manage_updatepro_thfn;
+static tpool_static_fn *manage_updatepro_cbfn;
+static tpool_static_fn *manage_unpackcode_thfn;
+static tpool_static_fn *manage_unpackcode_cbfn;
+static tpool_static_fn *manage_judge_thfn;
+static tpool_static_fn *manage_judge_cbfn;
+static std::multimap<int,judge_submit_info*> manage_submap;
+
+int judge_manage_init();
+int judge_manage_updatedata();
+judge_pro_info* judge_manage_getprobyid(int proid);
+int judge_manage_getpro(judge_pro_info *pro_info);
+int judge_manage_putpro(judge_pro_info *pro_info);
+int judge_manage_updatepro(int proid,int cacheid,bool check_flag,judge_pro_info **update_pro_info);
+int judge_manage_done_updatepro(judge_pro_info *pro_info);
+int judge_manage_submit(int subid,int proid,int lang,char *set_data,int set_len);
+int judge_manage_done_code(int subid);
+
+std::map<int,judge_pro_info*> judge_manage_promap;
+
+extern int tool_pack(char *pack_path,char *dir_path);
+extern int tool_unpack(char *pack_path,char *dir_path);
+extern int tool_cleardir(char *path);
+
+extern int judge_server_addtpool(tpool *tpinfo);
+extern int judge_server_setpro(std::vector<std::pair<int,int> > &pro_list);
+extern int judge_server_reqpro(int subid);
+extern int judge_server_reqcode(int subid);
+extern int judge_server_result(int subid,char *res_data,int res_len);
diff --git a/judge/judge_server.cpp b/judge/judge_server.cpp
new file mode 100644
index 0000000..66b4d01
--- /dev/null
+++ b/judge/judge_server.cpp
@@ -0,0 +1,515 @@
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<unistd.h>
+#include<fcntl.h>
+#include<dlfcn.h>
+#include<signal.h>
+#include<limits.h>
+#include<pthread.h>
+#include<semaphore.h>
+#include<errno.h>
+#include<sys/types.h>
+#include<sys/socket.h>
+#include<sys/epoll.h>
+#include<sys/eventfd.h>
+#include<sys/sendfile.h>
+#include<sys/mman.h>
+#include<netinet/in.h>
+#include<arpa/inet.h>
+#include<map>
+#include<queue>
+
+#include"netio.h"
+#include"tpool.h"
+#include"judge_def.h"
+#include"judge.h"
+#include"center_com.h"
+#include"judgm_line.h"
+#include"judgm_lib.h"
+#include"judge_server.h"
+
+server_epevdata::server_epevdata(int fd,int type,void *data){
+ this->fd = fd;
+ this->type = type;
+ this->data = data;
+}
+
+
+server_conn::server_conn(int fd):netio(fd){
+ this->recv_dispatch_fn = new netio_iofn<server_conn>(this,&server_conn::recv_dispatch);
+ this->recv_setid_fn = new netio_iofn<server_conn>(this,&server_conn::recv_setid);
+ this->recv_submit_fn = new netio_iofn<server_conn>(this,&server_conn::recv_submit);
+ this->recv_setpro_fn = new netio_iofn<server_conn>(this,&server_conn::recv_setpro);
+ this->recv_sendpro_fn = new netio_iofn<server_conn>(this,&server_conn::recv_sendpro);
+ this->done_sendpro_fn = new netio_iofn<server_conn>(this,&server_conn::done_sendpro);
+ this->recv_setjmod_fn = new netio_iofn<server_conn>(this,&server_conn::recv_setjmod);
+ this->recv_sendjmod_fn = new netio_iofn<server_conn>(this,&server_conn::recv_sendjmod);
+ this->done_sendjmod_fn = new netio_iofn<server_conn>(this,&server_conn::done_sendjmod);
+ this->recv_sendcode_fn = new netio_iofn<server_conn>(this,&server_conn::recv_sendcode);
+ this->done_sendcode_fn = new netio_iofn<server_conn>(this,&server_conn::done_sendcode);
+ this->tp_unpackjmod_thfn = new tpool_fn<server_conn>(this,&server_conn::tp_unpackjmod_th);
+ this->tp_unpackjmod_cbfn = new tpool_fn<server_conn>(this,&server_conn::tp_unpackjmod_cb);
+
+ send_setid();
+}
+char* server_conn::create_combuf(int code,int size,int &len,void **data){
+ char *buf;
+ center_com_header *header;
+
+ buf = new char[sizeof(center_com_header) + size];
+ header = (center_com_header*)buf;
+ header->code = code;
+ header->size = size;
+ len = sizeof(center_com_header) + size;
+ *data = (void*)(buf + sizeof(center_com_header));
+
+ return buf;
+}
+int server_conn::send_setid(){
+ char *write_buf;
+ int write_len;
+ center_com_setid *setid;
+
+ write_buf = create_combuf(CENTER_COMCODE_SETID,sizeof(center_com_setid),write_len,(void**)&setid);
+ setid->id = server_id;
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int server_conn::send_setinfo(){
+ char *write_buf;
+ int write_len;
+ center_com_setinfo *setinfo;
+
+ write_buf = create_combuf(CENTER_COMCODE_SETINFO,sizeof(center_com_setinfo),write_len,(void**)&setinfo);
+ setinfo->avail = server_avail;
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int server_conn::send_result(int subid,char *res_data,size_t res_len){
+ char *write_buf;
+ int write_len;
+ center_com_result *result;
+
+ if(res_len > JUDGE_RES_DATAMAX){
+ return -1;
+ }
+
+ write_buf = create_combuf(CENTER_COMCODE_RESULT,sizeof(center_com_result) + res_len,write_len,(void**)&result);
+ result->subid = subid;
+ memcpy((void*)(write_buf + sizeof(center_com_header) + sizeof(center_com_result)),res_data,res_len);
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int server_conn::send_reqpro(int proid,int cacheid){
+ char *write_buf;
+ int write_len;
+ center_com_reqpro *reqpro;
+
+ write_buf = create_combuf(CENTER_COMCODE_REQPRO,sizeof(center_com_reqpro),write_len,(void**)&reqpro);
+ reqpro->proid = proid;
+ reqpro->cacheid = cacheid;
+ writebytes(write_buf,write_len,NULL,NULL);
+}
+int server_conn::send_setpro(std::vector<std::pair<int,int> > &pro_list,int type){
+ int i;
+ int count;
+ char *write_buf;
+ int write_len;
+ center_com_setpro *setpro;
+ judge_pro_info *pro_info;
+
+ count = pro_list.size();
+ write_buf = create_combuf(CENTER_COMCODE_SETPRO,sizeof(center_com_setpro) * count,write_len,(void**)&setpro);
+
+ for(i = 0;i < count;i++){
+ setpro[i].proid = pro_list[i].first;
+ setpro[i].cacheid = pro_list[i].second;
+ setpro[i].type = type;
+ }
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int server_conn::send_setjmod(char **jmod_name,int *cacheid,int type,int count){
+ int i;
+
+ char *write_buf;
+ int write_len;
+ center_com_setjmod *setjmod;
+
+ write_buf = create_combuf(CENTER_COMCODE_SETJMOD,sizeof(center_com_setjmod) * count,write_len,(void**)&setjmod);
+ for(i = 0;i < count;i++){
+ setjmod[i].jmod_name[0] = '\0';
+ strncat(setjmod[i].jmod_name,jmod_name[i],sizeof(setjmod[i].jmod_name));
+ setjmod[i].cacheid = cacheid[i];
+ setjmod[i].type = type;
+ }
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int server_conn::send_reqcode(int subid){
+ char *write_buf;
+ int write_len;
+ center_com_reqcode *reqcode;
+
+ write_buf = create_combuf(CENTER_COMCODE_REQCODE,sizeof(center_com_reqcode),write_len,(void**)&reqcode);
+ reqcode->subid = subid;
+ writebytes(write_buf,write_len,NULL,NULL);
+
+ return 0;
+}
+int server_conn::readidle(){
+ readbytes(new center_com_header,sizeof(center_com_header),recv_dispatch_fn,NULL);
+ return 0;
+}
+void server_conn::recv_dispatch(void *buf,size_t len,void *data){
+ center_com_header *header;
+ char *readbuf;
+
+ header = (center_com_header*)buf;
+ readbuf = new char[header->size];
+ printf("code:%d size:%d\n",header->code,header->size);
+ switch(header->code){
+ case CENTER_COMCODE_SETID:
+ readbytes(readbuf,header->size,recv_setid_fn,NULL);
+ break;
+ case CENTER_COMCODE_SUBMIT:
+ readbytes(readbuf,header->size,recv_submit_fn,NULL);
+ break;
+ case CENTER_COMCODE_SETPRO:
+ readbytes(readbuf,header->size,recv_setpro_fn,NULL);
+ break;
+ case CENTER_COMCODE_SENDPRO:
+ readbytes(readbuf,header->size,recv_sendpro_fn,NULL);
+ break;
+ case CENTER_COMCODE_SETJMOD:
+ readbytes(readbuf,header->size,recv_setjmod_fn,NULL);
+ break;
+ case CENTER_COMCODE_SENDJMOD:
+ readbytes(readbuf,header->size,recv_sendjmod_fn,NULL);
+ break;
+ case CENTER_COMCODE_SENDCODE:
+ readbytes(readbuf,header->size,recv_sendcode_fn,NULL);
+ break;
+ }
+
+ delete header;
+}
+void server_conn::recv_setid(void *buf,size_t len,void *data){
+ center_com_setid *setid;
+
+ setid = (center_com_setid*)buf;
+ server_id = setid->id;
+ printf("server_id:%d\n",server_id);
+
+ //judge server init
+ send_setinfo();
+
+ delete setid;
+}
+void server_conn::recv_submit(void *buf,size_t len,void *data){
+ center_com_submit *sub;
+
+ sub = (center_com_submit*)buf;
+ judge_manage_submit(sub->subid,sub->proid,sub->lang,(char*)((char*)buf + sizeof(center_com_submit)),len - sizeof(center_com_submit));
+
+ delete sub;
+}
+void server_conn::recv_setpro(void *buf,size_t len,void *data){
+ int ret;
+ int i;
+ int count;
+ center_com_setpro *setpro;
+
+ char tpath[PATH_MAX + 1];
+ FILE *f;
+ int cacheid;
+ std::vector<std::pair<int,int> > pro_list;
+
+ count = len / sizeof(center_com_setpro);
+ setpro = (center_com_setpro*)buf;
+ for(i = 0;i < count;i++){
+ if(setpro[i].type == 0){
+ ret = judge_manage_updatepro(setpro[i].proid,setpro[i].cacheid,true,NULL);
+ if(ret == 0){
+ if(server_fileconn == NULL){
+ server_fileconn = server_connect();
+ }
+ server_fileconn->send_reqpro(setpro[i].proid,setpro[i].cacheid);
+ }else if(ret == 1){
+ pro_list.push_back(std::make_pair(setpro[i].proid,setpro[i].cacheid));
+ }
+ }else if(setpro[i].type == 1){
+
+ }
+ }
+
+ if(!pro_list.empty()){
+ this->send_setpro(pro_list,0);
+ }
+
+ delete setpro;
+}
+void server_conn::recv_sendpro(void *buf,size_t len,void *data){
+ center_com_sendpro *sendpro;
+ judge_pro_info *pro_info;
+ char tpath[PATH_MAX + 1];
+ int fd;
+
+ sendpro = (center_com_sendpro*)buf;
+
+ if(judge_manage_updatepro(sendpro->proid,sendpro->cacheid,false,&pro_info) == 0){
+ snprintf(tpath,sizeof(tpath),"tmp/propack/%d_%d.tar.bz2",sendpro->proid,sendpro->cacheid);
+ fd = open(tpath,O_WRONLY | O_CREAT,0644);
+ readfile(fd,sendpro->filesize,done_sendpro_fn,pro_info);
+ }
+
+ delete sendpro;
+}
+void server_conn::done_sendpro(void *buf,size_t len,void *data){
+ judge_pro_info *pro_info;
+
+ close(*(int*)buf);
+
+ pro_info = (judge_pro_info*)data;
+ judge_manage_done_updatepro(pro_info);
+}
+void server_conn::recv_setjmod(void *buf,size_t len,void *data){
+ int i;
+ int count;
+ center_com_setjmod *setjmod;
+
+ char tpath[PATH_MAX + 1];
+ FILE *f;
+ int cacheid;
+ std::vector<char*> sl_jmod_name;
+ std::vector<int> sl_cacheid;
+
+ char *write_buf;
+ int write_len;
+ center_com_reqjmod *reqjmod;
+
+ count = len / sizeof(center_com_setjmod);
+ setjmod = (center_com_setjmod*)buf;
+ for(i = 0;i < count;i++){
+ if(setjmod[i].type == 0){
+ snprintf(tpath,sizeof(tpath),"tmp/jmod/%s/cacheinfo",setjmod[i].jmod_name);
+ f = fopen(tpath,"r");
+ if(f != NULL){
+ fscanf(f,"%d",&cacheid);
+ fclose(f);
+
+ if(cacheid == setjmod[i].cacheid){
+ sl_jmod_name.push_back(setjmod[i].jmod_name);
+ sl_cacheid.push_back(setjmod[i].cacheid);
+ continue;
+ }
+ }
+
+ if(server_fileconn == NULL){
+ server_fileconn = server_connect();
+ }
+
+ write_buf = create_combuf(CENTER_COMCODE_REQJMOD,sizeof(center_com_reqjmod),write_len,(void**)&reqjmod);
+ reqjmod->jmod_name[0] = '\0';
+ strncat(reqjmod->jmod_name,setjmod[i].jmod_name,sizeof(reqjmod->jmod_name));
+ server_fileconn->writebytes(write_buf,write_len,NULL,NULL);
+ }else if(setjmod[i].type == 1){
+
+ }
+ }
+
+ if(!sl_jmod_name.empty()){
+ this->send_setjmod(&sl_jmod_name[0],&sl_cacheid[0],0,sl_jmod_name.size());
+ }
+
+ delete setjmod;
+}
+void server_conn::recv_sendjmod(void *buf,size_t len,void *data){
+ center_com_sendjmod *sendjmod;
+ char tpath[PATH_MAX + 1];
+ int fd;
+
+ sendjmod = (center_com_sendjmod*)buf;
+ snprintf(tpath,sizeof(tpath),"tmp/jmodpack/%s.tar.bz2",sendjmod->jmod_name);
+ fd = open(tpath,O_WRONLY | O_CREAT,0644);
+ readfile(fd,sendjmod->filesize,done_sendjmod_fn,sendjmod);
+}
+void server_conn::done_sendjmod(void *buf,size_t len,void *data){
+ center_com_sendjmod *sendjmod;
+
+ close(*(int*)buf);
+
+ sendjmod = (center_com_sendjmod*)data;
+ server_packtp->add(tp_unpackjmod_thfn,sendjmod,tp_unpackjmod_cbfn,sendjmod);
+}
+void server_conn::recv_sendcode(void *buf,size_t len,void *data){
+ center_com_sendcode *sendcode;
+ char tpath[PATH_MAX + 1];
+ int fd;
+
+ sendcode = (center_com_sendcode*)buf;
+ snprintf(tpath,sizeof(tpath),"tmp/codepack/%d.tar.bz2",sendcode->subid);
+ fd = open(tpath,O_WRONLY | O_CREAT,0644);
+ readfile(fd,sendcode->filesize,done_sendcode_fn,sendcode);
+}
+void server_conn::done_sendcode(void *buf,size_t len,void *data){
+ center_com_sendcode *sendcode;
+
+ close(*(int*)buf);
+
+ sendcode = (center_com_sendcode*)data;
+ judge_manage_done_code(sendcode->subid);
+
+ delete sendcode;
+}
+void server_conn::tp_unpackjmod_th(void *data){
+ center_com_sendjmod *sendjmod;
+ char pack_path[PATH_MAX + 1];
+ char dir_path[PATH_MAX + 1];
+ char tpath[PATH_MAX + 1];
+ FILE *f;
+
+ sendjmod = (center_com_sendjmod*)data;
+
+ snprintf(pack_path,sizeof(pack_path),"tmp/jmodpack/%s.tar.bz2",sendjmod->jmod_name);
+ snprintf(dir_path,sizeof(dir_path),"tmp/jmod/%s",sendjmod->jmod_name);
+ mkdir(dir_path,0755);
+ tool_cleardir(dir_path);
+ tool_unpack(pack_path,dir_path);
+
+ snprintf(tpath,sizeof(tpath),"tmp/jmod/%s/cacheinfo",sendjmod->jmod_name);
+ f = fopen(tpath,"w");
+ fprintf(f,"%d",sendjmod->cacheid);
+ fclose(f);
+}
+void server_conn::tp_unpackjmod_cb(void *data){
+ center_com_sendjmod *sendjmod;
+ char *jmod_name;
+
+ sendjmod = (center_com_sendjmod*)data;
+ jmod_name = sendjmod->jmod_name;
+ send_setjmod(&jmod_name,&sendjmod->cacheid,0,1);
+
+ delete sendjmod;
+}
+
+
+
+int judge_server_addtpool(tpool *tpinfo){
+ server_addepev(tpinfo->fd,EPOLLIN | EPOLLET,SERVER_EPEV_TPOOL,tpinfo);
+ return 0;
+}
+int judge_server_setpro(std::vector<std::pair<int,int> > &pro_list){
+ server_mainconn->send_setpro(pro_list,0);
+ return 0;
+}
+int judge_server_reqcode(int subid){
+ if(server_codeconn == NULL){
+ server_codeconn = server_connect();
+ }
+ server_codeconn->send_reqcode(subid);
+
+ return 0;
+}
+int judge_server_result(int subid,char *res_data,int res_len){
+ server_mainconn->send_result(subid,res_data,res_len);
+ return 0;
+}
+
+static int server_addepev(int fd,unsigned int flag,int type,void *data){
+ server_epevdata *epevdata;
+ epoll_event epev;
+
+ epevdata = new server_epevdata(fd,type,data);
+ epev.events = flag;
+ epev.data.ptr = epevdata;
+ epoll_ctl(server_epfd,EPOLL_CTL_ADD,fd,&epev);
+
+ return 0;
+}
+static int server_delepev(server_epevdata *epevdata){
+ epoll_ctl(server_epfd,EPOLL_CTL_DEL,epevdata->fd,NULL);
+ delete epevdata;
+ return 0;
+}
+static server_conn* server_connect(){
+ int cfd;
+ sockaddr_in caddr;
+ epoll_event epev;
+ server_conn *cinfo;
+
+ cfd = socket(AF_INET,SOCK_STREAM | SOCK_NONBLOCK,6);
+ caddr.sin_family = AF_INET;
+ caddr.sin_port = htons(SERVER_JUDGE_PORT);
+ //caddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ caddr.sin_addr.s_addr = inet_addr("10.8.0.2");
+
+ cinfo = new server_conn(cfd);
+ server_addepev(cfd,EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET,SERVER_EPEV_JUDGECLIENT,cinfo);
+ connect(cfd,(sockaddr*)&caddr,sizeof(caddr));
+
+ return cinfo;
+}
+int main(){
+ int i;
+
+ epoll_event epev;
+ epoll_event epevs[SERVER_EPOLL_MAXEVENT];
+ int nevs;
+
+ int ev_flag;
+ server_epevdata *epevdata;
+ server_conn *cinfo;
+ tpool *tpinfo;
+
+ signal(SIGPIPE,SIG_IGN);
+ server_epfd = epoll_create1(0);
+
+ server_id = 0;
+ server_avail = JUDGE_THREAD_JUDGEMAX;
+ server_mainconn = server_connect();
+ server_fileconn = NULL;
+ server_codeconn = NULL;
+
+ judge_manage_init();
+
+ server_packtp = new tpool(4);
+ judge_server_addtpool(server_packtp);
+ server_packtp->start();
+
+
+ while(true){
+ nevs = epoll_wait(server_epfd,epevs,SERVER_EPOLL_MAXEVENT,-1);
+ for(i = 0;i < nevs;i++){
+ ev_flag = epevs[i].events;
+ epevdata = (server_epevdata*)epevs[i].data.ptr;
+
+ if(epevdata->type == SERVER_EPEV_JUDGECLIENT){
+ cinfo = (server_conn*)epevdata->data;
+ if(ev_flag & EPOLLIN){
+ cinfo->readio();
+ }
+ if(ev_flag & EPOLLOUT){
+ cinfo->writeio();
+ }
+
+ server_packtp->done();
+ }else if(epevdata->type = SERVER_EPEV_TPOOL){
+ tpinfo = (tpool*)epevdata->data;
+ if(ev_flag & EPOLLIN){
+ tpinfo->done();
+ }
+ }
+ }
+ }
+
+ close(server_epfd);
+
+ return 0;
+}
diff --git a/judge/judge_server.h b/judge/judge_server.h
new file mode 100644
index 0000000..90a4e7c
--- /dev/null
+++ b/judge/judge_server.h
@@ -0,0 +1,87 @@
+#define SERVER_JUDGE_PORT 2573
+#define SERVER_EPOLL_MAXEVENT 4096
+
+#define SERVER_EPEV_JUDGECLIENT 0
+#define SERVER_EPEV_TPOOL 1
+class server_epevdata{
+public:
+ int fd;
+ int type;
+ void *data;
+
+ server_epevdata(int fd,int type,void *data);
+};
+
+class server_conn : public netio{
+private:
+ netio_iofn<server_conn> *recv_dispatch_fn;
+ netio_iofn<server_conn> *recv_setid_fn;
+ netio_iofn<server_conn> *recv_submit_fn;
+ netio_iofn<server_conn> *recv_setpro_fn;
+ netio_iofn<server_conn> *recv_sendpro_fn;
+ netio_iofn<server_conn> *done_sendpro_fn;
+ netio_iofn<server_conn> *recv_setjmod_fn;
+ netio_iofn<server_conn> *recv_sendjmod_fn;
+ netio_iofn<server_conn> *done_sendjmod_fn;
+ netio_iofn<server_conn> *recv_sendcode_fn;
+ netio_iofn<server_conn> *done_sendcode_fn;
+ tpool_fn<server_conn> *tp_unpackjmod_thfn;
+ tpool_fn<server_conn> *tp_unpackjmod_cbfn;
+
+ char* create_combuf(int code,int size,int &len,void **data);
+ void recv_dispatch(void *buf,size_t len,void *data);
+ void recv_setid(void *buf,size_t len,void *data);
+ void recv_submit(void *buf,size_t len,void *data);
+ void recv_setpro(void *buf,size_t len,void *data);
+ void recv_sendpro(void *buf,size_t len,void *data);
+ void done_sendpro(void *buf,size_t len,void *data);
+ void recv_setjmod(void *buf,size_t len,void *data);
+ void recv_sendjmod(void *buf,size_t len,void *data);
+ void done_sendjmod(void *buf,size_t len,void *data);
+ void recv_sendcode(void *buf,size_t len,void *data);
+ void done_sendcode(void *buf,size_t len,void *data);
+ void tp_unpackjmod_th(void *data);
+ void tp_unpackjmod_cb(void *data);
+
+public:
+ server_conn(int fd);
+ int send_setid();
+ int send_setinfo();
+ int send_result(int subid,char *res_data,size_t res_len);
+ int send_reqpro(int proid,int cacheid);
+ int send_setpro(std::vector<std::pair<int,int> > &pro_list,int type);
+ int send_setjmod(char **jmod_name,int *cacheid,int type,int count);
+ int send_reqcode(int subid);
+ virtual int readidle();
+};
+
+static int server_addepev(int fd,unsigned int flag,int type,void *data);
+static int server_delepev(server_epevdata *epevdata);
+static server_conn* server_connect();
+
+static int server_id;
+static int server_avail;
+static int server_epfd;
+static server_conn *server_mainconn;
+static server_conn *server_fileconn;
+static server_conn *server_codeconn;
+static tpool *server_packtp;
+
+int judge_server_addtpool(tpool *tpinfo);
+int judge_server_setpro(std::vector<std::pair<int,int> > &pro_list);
+int judge_server_reqcode(int subid);
+int judge_server_result(int subid,char *res_data,int res_len);
+
+extern int tool_pack(char *pack_path,char *dir_path);
+extern int tool_unpack(char *pack_path,char *dir_path);
+extern int tool_cleardir(char *path);
+
+extern int judge_manage_init();
+extern judge_pro_info* judge_manage_getprobyid(int proid);
+extern int judge_manage_getpro(judge_pro_info *pro_info);
+extern int judge_manage_putpro(judge_pro_info *pro_info);
+extern int judge_manage_updatepro(int proid,int cacheid,bool check_flag,judge_pro_info **update_pro_info);
+extern int judge_manage_done_updatepro(judge_pro_info *pro_info);
+extern int judge_manage_submit(int subid,int proid,int lang,char *set_data,int set_len);
+extern int judge_manage_done_code(int subid);
+
diff --git a/judge/judgm_lib.h b/judge/judgm_lib.h
new file mode 100644
index 0000000..041901d
--- /dev/null
+++ b/judge/judgm_lib.h
@@ -0,0 +1,418 @@
+#include<string.h>
+#include<limits.h>
+#include<unistd.h>
+#include<signal.h>
+#include<limits.h>
+#include<errno.h>
+#include<pthread.h>
+#include<semaphore.h>
+#include<fcntl.h>
+#include<sys/ioctl.h>
+#include<sys/resource.h>
+#include<sys/stat.h>
+#include<sys/types.h>
+#include<sys/wait.h>
+#include<sys/mman.h>
+#include<map>
+#include<utility>
+
+#include"judge.h"
+
+typedef int (*judgm_proc_check_fn)();
+
+class judgm_proc{
+private:
+ int init(){
+ int i;
+ int j;
+ struct stat st;
+
+ if(stat(exe_path,&st)){
+ return -1;
+ }
+ if(!S_ISREG(st.st_mode)){
+ return -1;
+ }
+
+ exe_name[NAME_MAX] = '\0';
+ for(i = 0,j = 0;exe_path[i] != '\0' && j < NAME_MAX;i++){
+ if(exe_path[i] == '/'){
+ j = 0;
+ }else{
+ exe_name[j] = exe_path[i];
+ j++;
+ }
+ }
+ exe_name[j] = '\0';
+
+ pid = 0;
+ kern_task = 0;
+ status = JUDGE_WAIT;
+ runtime = 0;
+ memory = 0;
+
+ return 0;
+ }
+ int protect(){
+ rlimit limit;
+ judgk_com_proc_add com_proc_add;
+
+ limit.rlim_cur = 1;
+ limit.rlim_max = limit.rlim_cur;
+ prlimit(pid,RLIMIT_NPROC,&limit,NULL);
+
+ limit.rlim_cur = 8L;
+ limit.rlim_max = limit.rlim_cur;
+ prlimit(pid,RLIMIT_NOFILE,&limit,NULL);
+
+ limit.rlim_cur = 70368744177664L;
+ limit.rlim_max = limit.rlim_cur;
+ prlimit(pid,RLIMIT_STACK,&limit,NULL);
+
+ com_proc_add.run_path[0] = '\0';
+ strncat(com_proc_add.run_path,run_path,sizeof(com_proc_add.run_path));
+ com_proc_add.pid = pid;
+ com_proc_add.timelimit = timelimit * 1000L;
+ com_proc_add.hardtimelimit = hardtimelimit * 1000L;
+ com_proc_add.memlimit = memlimit * 1024L + 4096L * 128L;
+ if(ioctl(judgk_modfd,IOCTL_PROC_ADD,&com_proc_add)){
+ return -1;
+ }
+ kern_task = com_proc_add.kern_task;
+
+ return 0;
+ }
+
+public:
+ int judgk_modfd;
+ char run_path[PATH_MAX + 1];
+ char exe_path[PATH_MAX + 1];
+ char exe_name[NAME_MAX + 1];
+ unsigned long timelimit;
+ unsigned long hardtimelimit;
+ unsigned long memlimit;
+ judgm_proc_check_fn check_fn;
+
+ pid_t pid;
+ unsigned long kern_task;
+ int status;
+ unsigned long runtime;
+ unsigned long memory;
+
+ judgm_proc(int judgk_modfd,char *runpath,char *exe_path,unsigned long timelimit,unsigned long hardtimelimit,unsigned long memlimit,judgm_proc_check_fn check_fn){
+ this->judgk_modfd = judgk_modfd;
+ this->run_path[0] = '\0';
+ strncat(this->run_path,runpath,sizeof(this->run_path));
+ this->exe_path[0] = '\0';
+ strncat(this->exe_path,exe_path,sizeof(this->exe_path));
+
+ this->timelimit = timelimit;
+ this->hardtimelimit = hardtimelimit;
+ this->memlimit = memlimit;
+ this->check_fn = check_fn;
+ }
+
+ int proc_run(){
+ char abspath[PATH_MAX + 1];
+
+ if(init()){
+ return -1;
+ }
+
+ realpath(exe_path,abspath);
+ if((pid = fork()) == 0){
+ char *argv[] = {NULL,NULL};
+ char *envp[] = {NULL};
+
+ chdir(run_path);
+ check_fn();
+
+ setgid(99);
+ setuid(99);
+ kill(getpid(),SIGSTOP);
+
+ argv[0] = exe_name;
+ execve(abspath,argv,envp);
+ exit(0);
+ }
+
+ if(pid == -1){
+ return -1;
+ }
+ waitpid(pid,NULL,WUNTRACED);
+
+ if(protect()){
+ kill(pid,SIGKILL);
+ return -1;
+ }
+ status = JUDGE_RUN;
+ kill(pid,SIGCONT);
+
+ return 0;
+ }
+ int proc_wait(bool blockflag){
+ int wstatus;
+ struct judgk_com_proc_get com_proc_get;
+
+ if(blockflag == true){
+ if(waitpid(pid,&wstatus,WUNTRACED) == -1){
+ return -1;
+ }
+ }else{
+ if(waitpid(pid,&wstatus,WUNTRACED | WNOHANG) <= 0){
+ return -1;
+ }
+ }
+
+ com_proc_get.kern_task = kern_task;
+ if(ioctl(judgk_modfd,IOCTL_PROC_GET,&com_proc_get)){
+ return -1;
+ }
+
+ runtime = com_proc_get.runtime / 1000L;
+ memory = com_proc_get.memory;
+
+ printf("runtime:%lu memory:%lu\n",runtime,memory);
+
+ if(com_proc_get.status != JUDGE_AC){
+ status = com_proc_get.status;
+ }else if(memory > (memlimit * 1024L)){
+ status = JUDGE_MLE;
+ }else if(runtime > timelimit){
+ status = JUDGE_TLE;
+ }else if(WIFEXITED(wstatus) || (WIFSIGNALED(wstatus) && WTERMSIG(wstatus) == SIGKILL)){
+ status = JUDGE_AC;
+ }else{
+ status = JUDGE_RE;
+ }
+
+ return 0;
+ }
+ int proc_kill(){
+ if(kill(pid,SIGKILL)){
+ return -1;
+ }
+ return 0;
+ }
+};
+
+class judgm_hyperio{
+private:
+ int judgk_modfd;
+ char *read_buf;
+ off_t read_off;
+
+public:
+ int tty_idx;
+
+ judgm_hyperio(int judgk_modfd){
+ this->judgk_modfd = judgk_modfd;
+ this->tty_idx = ioctl(this->judgk_modfd,IOCTL_HYPERIO_ADD,0);
+ this->read_buf = (char*)mmap(NULL,JUDGK_COM_HYPERIO_BUFSIZE,PROT_READ,MAP_SHARED,judgk_modfd,0);
+ this->read_off = 0;
+ }
+ ~judgm_hyperio(){
+ munmap(read_buf,JUDGK_COM_HYPERIO_BUFSIZE);
+ ioctl(judgk_modfd,IOCTL_HYPERIO_DEL,0);
+ }
+
+ static int get_ttyfd(int idx){
+ char tpath[PATH_MAX + 1];
+
+ snprintf(tpath,sizeof(tpath),"/dev/jtty%d",idx);
+ return open(tpath,O_RDWR);
+ }
+ size_t wait(){
+ return ioctl(judgk_modfd,IOCTL_HYPERIO_READ,0);
+ }
+ int compare(char *buf,size_t len){
+ int flag;
+ size_t remain;
+ off_t off;
+ size_t data_len;
+ size_t cmp_len;
+
+ flag = 0;
+ remain = len;
+ off = 0;
+ data_len = 0;
+ cmp_len = 0;
+ while(remain > 0 && flag == 0){
+ if(data_len == 0){
+ if((data_len = ioctl(judgk_modfd,IOCTL_HYPERIO_READ,cmp_len)) <= 0){
+ return -1;
+ }
+ }
+ if(remain < data_len){
+ cmp_len = remain;
+ }else{
+ cmp_len = data_len;
+ }
+
+ if((cmp_len + read_off) < JUDGK_COM_HYPERIO_BUFSIZE){
+ flag |= memcmp(read_buf + read_off,buf + off,cmp_len);
+ read_off += cmp_len;
+ }else{
+ flag |= memcmp(read_buf + read_off,buf + off,JUDGK_COM_HYPERIO_BUFSIZE - read_off);
+ flag |= memcmp(read_buf,buf + off + (JUDGK_COM_HYPERIO_BUFSIZE - read_off),(cmp_len + read_off) - JUDGK_COM_HYPERIO_BUFSIZE);
+ read_off = (cmp_len + read_off) - JUDGK_COM_HYPERIO_BUFSIZE;
+ }
+ remain -= cmp_len;
+ off += cmp_len;
+ data_len -= cmp_len;
+ }
+ if(cmp_len > 0){
+ ioctl(judgk_modfd,IOCTL_HYPERIO_READ,-(long)cmp_len);
+ }
+
+ if(flag == 0){
+ return 0;
+ }else{
+ return -1;
+ }
+ }
+};
+
+static int judgm_compile(int subid,char *code_path,char *exe_path,int lang,bool force_flag,char *err_msg,size_t err_len){
+ int ret;
+ int i;
+
+ char log_path[PATH_MAX + 1];
+ char main_path[PATH_MAX + 1];
+ char sem_path[PATH_MAX + 1];
+ struct stat st;
+ sem_t *wait_sem;
+ bool ce_flag;
+ char dir_path[PATH_MAX + 1];
+ char *out_path;
+ int io[2];
+ int pid;
+ int wstatus;
+ char buf[64];
+ off_t err_off;
+ FILE *f_log;
+
+ if(force_flag == true){
+ force_flag = true;
+ out_path = exe_path;
+ }else{
+ snprintf(log_path,sizeof(log_path),"tmp/exe/%d/log",subid);
+ snprintf(main_path,sizeof(main_path),"tmp/exe/%d/main",subid);
+ snprintf(sem_path,sizeof(sem_path),"/judgm_compile_wait_%d",subid);
+ if((wait_sem = sem_open(sem_path,0)) == SEM_FAILED){
+ if(stat(main_path,&st)){
+ if((wait_sem = sem_open(sem_path,O_CREAT | O_EXCL,0644,0)) != SEM_FAILED){
+ out_path = main_path;
+ goto compile;
+ }else if((wait_sem = sem_open(sem_path,0)) != SEM_FAILED){
+
+ sem_wait(wait_sem);
+
+ sem_close(wait_sem);
+ }
+ }
+ }else{
+
+ sem_wait(wait_sem);
+
+ sem_close(wait_sem);
+ }
+
+ if((f_log = fopen(log_path,"r")) != NULL){
+ err_off = fread(err_msg,1,err_len - 1,f_log);
+ fclose(f_log);
+ err_msg[err_off] = '\0';
+
+ if(!link(main_path,exe_path)){
+ return 0;
+ }else{
+ return -1;
+ }
+ }
+ }
+
+compile:
+
+ if(force_flag == false){
+ snprintf(dir_path,sizeof(dir_path),"tmp/exe/%d",subid);
+ mkdir(dir_path,0755);
+ }
+ ce_flag = false;
+ err_off = 0;
+
+ if(lang == JUDGE_CPP){
+ pipe(io);
+
+ if((pid = fork()) == 0){
+ char arg_compiler[16];
+ char arg_static[16];
+ char arg_o[16];
+ char arg_std[16];
+ char arg_output[16];
+ char *argv[8];
+
+ arg_compiler[0] = '\0';
+ strncat(arg_compiler,"g++",sizeof(arg_compiler));
+ arg_static[0] = '\0';
+ strncat(arg_static,"-static",sizeof(arg_static));
+ arg_o[0] = '\0';
+ strncat(arg_o,"-O2",sizeof(arg_o));
+ arg_std[0] = '\0';
+ strncat(arg_std,"-std=c++0x",sizeof(arg_std));
+ arg_output[0] = '\0';
+ strncat(arg_output,"-o",sizeof(arg_output));
+
+ argv[0] = arg_compiler;
+ argv[1] = arg_static;
+ argv[2] = arg_o;
+ argv[3] = code_path;
+ argv[4] = arg_std;
+ argv[5] = arg_output;
+ argv[6] = out_path;
+ argv[7] = NULL;
+
+ dup2(io[1],1);
+ dup2(io[1],2);
+ execvp("g++",argv);
+ }
+
+ close(io[1]);
+ while((ret = read(io[0],err_msg + err_off,err_len - err_off - 1)) > 0){
+ err_off += ret;
+ }
+ err_msg[err_off] = '\0';
+
+ while(read(io[0],buf,64) > 0);
+ close(io[0]);
+
+ if(err_off > (err_len - 4)){
+ err_msg[err_len - 4] = '\0';
+ strncat(err_msg + err_len - 4,"...",4);
+ err_off = err_len - 1;
+ }
+
+ waitpid(pid,&wstatus,0);
+ if(wstatus != 0){
+ ce_flag = true;
+ }
+ }
+
+ if(force_flag == false){
+ f_log = fopen(log_path,"w");
+ fwrite(err_msg,err_off,1,f_log);
+ fclose(f_log);
+
+ for(i = 0;i < JUDGE_THREAD_MAX;i++){
+ sem_post(wait_sem);
+ }
+ sem_close(wait_sem);
+ sem_unlink(sem_path);
+ }
+ if(ce_flag == true){
+ return -1;
+ }
+
+ link(main_path,exe_path);
+
+ return 0;
+}
diff --git a/judge/judgm_line.h b/judge/judgm_line.h
new file mode 100644
index 0000000..1b36c74
--- /dev/null
+++ b/judge/judgm_line.h
@@ -0,0 +1,19 @@
+struct judgm_line_info{
+ int subid;
+
+ char *pro_path;
+ char *code_path;
+ char *run_path;
+
+ int judgk_modfd;
+ void *line_dll;
+ void *check_dll;
+
+ int lang;
+ FILE *set_file;
+ char *set_data;
+
+ char res_data[JUDGE_RES_DATAMAX];
+ size_t res_len;
+};
+typedef int (*judgm_line_run_fn)(judgm_line_info *info);
diff --git a/judge/judgm_manage.h b/judge/judgm_manage.h
new file mode 100644
index 0000000..2795ec7
--- /dev/null
+++ b/judge/judgm_manage.h
@@ -0,0 +1,29 @@
+typedef int (*judgm_manage_queuesubmit_fn)(int subid,int proid,int lang,char *set_data,size_t set_len);
+
+class judgm_manage_info{
+public:
+ int subid;
+ int uid;
+ int proid;
+ int lang;
+ char *param;
+ char pro_path[PATH_MAX + 1];
+ char res_path[PATH_MAX + 1];
+
+ int result;
+ double score;
+ unsigned long runtime;
+ unsigned long memory;
+
+ void *private_data;
+
+ judgm_manage_info(int subid,int uid,int proid,int lang,char *param){
+ this->subid = subid;
+ this->uid = uid;
+ this->proid = proid;
+ this->lang = lang;
+ this->param = param;
+ }
+};
+typedef int (*judgm_manage_submit_fn)(judgm_manage_info *info,FILE *set_file);
+typedef int (*judgm_manage_result_fn)(judgm_manage_info *info,char *res_data);
diff --git a/judge/netio.h b/judge/netio.h
new file mode 100644
index 0000000..db54b23
--- /dev/null
+++ b/judge/netio.h
@@ -0,0 +1,192 @@
+class netio_protoiofn{
+public:
+ virtual void operator()(void *buf,size_t len,void *data) = 0;
+};
+
+template<typename C>
+class netio_iofn : public netio_protoiofn{
+private:
+ typedef void (C::*netio_iofn_type)(void *buf,size_t len,void *data);
+ C *obj;
+ netio_iofn_type fn;
+
+public:
+ netio_iofn(C *obj,netio_iofn_type fn){
+ this->obj = obj;
+ this->fn = fn;
+ }
+ void operator()(void *buf,size_t len,void *data){
+ (obj->*fn)(buf,len,data);
+ }
+};
+
+#define NETIO_IOTYPE_PLAIN 0
+#define NETIO_IOTYPE_FILE 1
+class netio_iocb{
+public:
+ int type;
+
+ void *buf;
+ int fd;
+ off_t off;
+ size_t len;
+ netio_protoiofn *cb_fn;
+ void *cb_data;
+
+ netio_iocb(void *buf,size_t len,netio_protoiofn *cb_fn,void *cb_data){
+ this->type = NETIO_IOTYPE_PLAIN;
+ this->buf = buf;
+ this->off = 0;
+ this->len = len;
+ this->cb_fn = cb_fn;
+ this->cb_data = cb_data;
+ }
+ netio_iocb(int fd,size_t len,netio_protoiofn *cb_fn,void *cb_data){
+ this->type = NETIO_IOTYPE_FILE;
+ this->buf = &this->fd;
+ this->fd = fd;
+ this->off = 0;
+ this->len = len;
+ this->cb_fn = cb_fn;
+ this->cb_data = cb_data;
+ }
+};
+
+#define NETIO_IOSIZE 65536
+class netio{
+private:
+ netio_iocb *read_iocb;
+ std::queue<netio_iocb*> write_queue;
+ bool readio_reen;
+ char readio_buf[NETIO_IOSIZE];
+
+public:
+ int fd;
+ virtual int readidle() = 0;
+
+ netio(int fd){
+ this->fd = fd;
+ this->read_iocb = NULL;
+ this->readio_reen = false;
+ }
+ ~netio(){
+ close(this->fd);
+ }
+ int readio(){
+ int ret;
+ size_t len;
+ netio_iocb *iocb;
+
+ if(readio_reen == true){
+ return -1;
+ }
+ readio_reen = true;
+
+ while(true){
+ if(read_iocb == NULL){
+ readidle();
+ }
+
+ iocb = read_iocb;
+ if(iocb->type == NETIO_IOTYPE_PLAIN){
+ while((ret = read(fd,(char*)iocb->buf + iocb->off,iocb->len - iocb->off)) > 0){
+ iocb->off += ret;
+ }
+ }else if(iocb->type == NETIO_IOTYPE_FILE){
+ while(true){
+ len = iocb->len - iocb->off;
+ if(len >= NETIO_IOSIZE){
+ len = NETIO_IOSIZE;
+ }
+ if((ret = read(fd,readio_buf,len)) <= 0){
+ break;
+ }
+
+ write(iocb->fd,readio_buf,ret);
+ iocb->off += ret;
+ }
+ }
+ if(iocb->off == iocb->len){
+ read_iocb = NULL;
+
+ if(iocb->cb_fn != NULL){
+ (*iocb->cb_fn)(iocb->buf,iocb->len,iocb->cb_data);
+ }else{
+ if(iocb->type == NETIO_IOTYPE_PLAIN){
+ delete (char*)iocb->buf;
+ }else if(iocb->type == NETIO_IOTYPE_FILE){
+ close(iocb->fd);
+ }
+ }
+
+ delete iocb;
+ }else{
+ break;
+ }
+ }
+
+ readio_reen = false;
+ return 0;
+ }
+ int readbytes(void *buf,size_t len,netio_protoiofn *cb_fn,void *cb_data){
+ read_iocb = new netio_iocb(buf,len,cb_fn,cb_data);
+ readio();
+ return 0;
+ }
+ int readfile(int fd,size_t len,netio_protoiofn *cb_fn,void *cb_data){
+ read_iocb = new netio_iocb(fd,len,cb_fn,cb_data);
+ readio();
+ return 0;
+ }
+ int writeio(){
+ int ret;
+ size_t len;
+ netio_iocb *iocb;
+
+ while(!write_queue.empty()){
+ iocb = write_queue.front();
+ if(iocb->type == NETIO_IOTYPE_PLAIN){
+ while((ret = write(fd,(char*)iocb->buf + iocb->off,iocb->len - iocb->off)) > 0){
+ iocb->off += ret;
+ }
+ }else if(iocb->type == NETIO_IOTYPE_FILE){
+ len = iocb->len - iocb->off;
+ if(len >= NETIO_IOSIZE){
+ len = NETIO_IOSIZE;
+ }
+ while((ret = sendfile(fd,iocb->fd,NULL,len)) > 0){
+ iocb->off += ret;
+ }
+ }
+ if(iocb->off == iocb->len){
+ write_queue.pop();
+
+ if(iocb->cb_fn != NULL){
+ (*iocb->cb_fn)(iocb->buf,iocb->len,iocb->cb_data);
+ }else{
+ if(iocb->type == NETIO_IOTYPE_PLAIN){
+ delete (char*)iocb->buf;
+ }else if(iocb->type == NETIO_IOTYPE_FILE){
+ close(iocb->fd);
+ }
+ }
+
+ delete iocb;
+ }else{
+ break;
+ }
+ }
+
+ return 0;
+ }
+ int writebytes(void *buf,size_t len,netio_protoiofn *cb_fn,void *cb_data){
+ write_queue.push(new netio_iocb(buf,len,cb_fn,cb_data));
+ writeio();
+ return 0;
+ }
+ int writefile(int fd,size_t len,netio_protoiofn *cb_fn,void *cb_data){
+ write_queue.push(new netio_iocb(fd,len,cb_fn,cb_data));
+ writeio();
+ return 0;
+ }
+};
diff --git a/judge/tool.cpp b/judge/tool.cpp
new file mode 100644
index 0000000..b4a302d
--- /dev/null
+++ b/judge/tool.cpp
@@ -0,0 +1,294 @@
+#include<string.h>
+#include<dirent.h>
+#include<unistd.h>
+#include<fcntl.h>
+#include<limits.h>
+#include<ftw.h>
+#include<libtar.h>
+#include<bzlib.h>
+#include<sys/stat.h>
+#include<sys/sendfile.h>
+#include<map>
+#include<vector>
+#include<string>
+
+#include"tool.h"
+
+static int pack_copenfn(const char *pathname,int flags,...){
+ int fd;
+ pack_bzinfo *bzinfo;
+
+ if((fd = open(pathname,flags,0644)) == -1){
+ return -1;
+ }
+
+ bzinfo = new pack_bzinfo;
+ bzinfo->len = 0;
+ bzinfo->off = 0;
+ bzinfo->endflag = false;
+ bzinfo->bzs.bzalloc = NULL;
+ bzinfo->bzs.bzfree = NULL;
+ bzinfo->bzs.opaque = NULL;
+ BZ2_bzCompressInit(&bzinfo->bzs,9,0,0);
+
+ pack_fdmap.insert(std::pair<int,pack_bzinfo*>(fd,bzinfo));
+
+ return fd;
+}
+static int pack_cclosefn(long fd){
+ int ret;
+ pack_bzinfo *bzinfo;
+
+ bzinfo = pack_fdmap.find(fd)->second;
+ pack_fdmap.erase(fd);
+
+ bzinfo->bzs.next_in = NULL;
+ bzinfo->bzs.avail_in = 0;
+ while(true){
+ bzinfo->bzs.next_out = bzinfo->buf;
+ bzinfo->bzs.avail_out = PACK_BUFSIZE;
+ ret = BZ2_bzCompress(&bzinfo->bzs,BZ_FINISH);
+
+ if(bzinfo->bzs.avail_out != PACK_BUFSIZE){
+ write(fd,bzinfo->buf,PACK_BUFSIZE - bzinfo->bzs.avail_out);
+ }
+ if(ret == BZ_STREAM_END){
+ break;
+ }
+ }
+
+ BZ2_bzCompressEnd(&bzinfo->bzs);
+ delete bzinfo;
+ return close(fd);
+}
+static ssize_t pack_cwritefn(long fd,const void *buf,size_t count){
+ pack_bzinfo *bzinfo;
+
+ bzinfo = pack_fdmap.find(fd)->second;
+
+ bzinfo->bzs.next_in = (char*)buf;
+ bzinfo->bzs.avail_in = count;
+ while(bzinfo->bzs.avail_in > 0){
+ bzinfo->bzs.next_out = bzinfo->buf;
+ bzinfo->bzs.avail_out = PACK_BUFSIZE;
+ BZ2_bzCompress(&bzinfo->bzs,BZ_RUN);
+ if(bzinfo->bzs.avail_out != PACK_BUFSIZE){
+ write(fd,bzinfo->buf,PACK_BUFSIZE - bzinfo->bzs.avail_out);
+ }
+ }
+
+ return count;
+}
+static int pack_xopenfn(const char *pathname,int flags,...){
+ int fd;
+ pack_bzinfo *bzinfo;
+
+ if((fd = open(pathname,flags)) == -1){
+ return -1;
+ }
+
+ bzinfo = new pack_bzinfo;
+ bzinfo->len = 0;
+ bzinfo->off = 0;
+ bzinfo->endflag = false;
+ bzinfo->bzs.bzalloc = NULL;
+ bzinfo->bzs.bzfree = NULL;
+ bzinfo->bzs.opaque = NULL;
+ BZ2_bzDecompressInit(&bzinfo->bzs,0,0);
+
+ pack_fdmap.insert(std::pair<int,pack_bzinfo*>(fd,bzinfo));
+
+ return fd;
+}
+static int pack_xclosefn(long fd){
+ int ret;
+ pack_bzinfo *bzinfo;
+
+ bzinfo = pack_fdmap.find(fd)->second;
+ pack_fdmap.erase(fd);
+ BZ2_bzDecompressEnd(&bzinfo->bzs);
+ delete bzinfo;
+
+ return close(fd);
+}
+static ssize_t pack_xreadfn(long fd,void *buf,size_t count){
+ int ret;
+ pack_bzinfo *bzinfo;
+
+ bzinfo = pack_fdmap.find(fd)->second;
+
+ bzinfo->bzs.next_out = (char*)buf;
+ bzinfo->bzs.avail_out = count;
+ while(bzinfo->endflag == false){
+ if(bzinfo->len == 0){
+ ret = read(fd,bzinfo->buf,PACK_BUFSIZE);
+ bzinfo->len = ret;
+ bzinfo->off = 0;
+ }
+ if(bzinfo->len == 0){
+ break;
+ }
+
+ bzinfo->bzs.next_in = bzinfo->buf + bzinfo->off;
+ bzinfo->bzs.avail_in = bzinfo->len;
+ while(bzinfo->bzs.avail_in > 0 && bzinfo->bzs.avail_out > 0){
+ if(BZ2_bzDecompress(&bzinfo->bzs) != BZ_OK){
+ bzinfo->endflag = true;
+ break;
+ }
+ }
+ bzinfo->off += bzinfo->len - bzinfo->bzs.avail_in;
+ bzinfo->len = bzinfo->bzs.avail_in;
+
+ if(bzinfo->bzs.avail_out == 0){
+ break;
+ }
+ }
+
+ return count - bzinfo->bzs.avail_out;
+}
+
+int tool_pack(char *pack_path,char *dir_path){
+ tartype_t tar_type;
+ TAR *tarp;
+ char tpath[2] = {'.','\0'};
+
+ tar_type.openfunc = pack_copenfn;
+ tar_type.closefunc = pack_cclosefn;
+ tar_type.readfunc = (readfunc_t)read;
+ tar_type.writefunc = pack_cwritefn;
+ tar_open(&tarp,pack_path,&tar_type,O_WRONLY | O_CREAT,0644,TAR_GNU);
+
+ tar_append_tree(tarp,dir_path,tpath);
+ tar_close(tarp);
+
+ return 0;
+}
+int tool_unpack(char *pack_path,char *dir_path){
+ tartype_t tar_type;
+ TAR *tarp;
+
+ tool_cleardir(dir_path);
+ mkdir(dir_path,0775);
+
+ tar_type.openfunc = pack_xopenfn;
+ tar_type.closefunc = pack_xclosefn;
+ tar_type.readfunc = pack_xreadfn;
+ tar_type.writefunc = (writefunc_t)write;
+ tar_open(&tarp,pack_path,&tar_type,O_RDONLY,0644,TAR_GNU);
+
+ tar_extract_all(tarp,dir_path);
+ tar_close(tarp);
+
+ return 0;
+}
+
+static int cleardir_callback(const char *path,const struct stat *st,int flag,struct FTW *ftw_buf){
+ if(ftw_buf->level == 0){
+ return 0;
+ }
+
+ if(S_ISDIR(st->st_mode)){
+ rmdir(path);
+ }else{
+ unlink(path);
+ }
+ return 0;
+}
+int tool_cleardir(char *path){
+ nftw(path,cleardir_callback,64,FTW_DEPTH | FTW_PHYS);
+ return 0;
+}
+static int copydir_travel(char *old_path,int old_len,char *new_path,int new_len){
+ int i;
+ int j;
+ int len;
+
+ DIR *dirp;
+ char *buf;
+ dirent *entry;
+ std::vector<std::string> wait_list;
+ const char *tname;
+
+ int infd;
+ int outfd;
+ struct stat st;
+
+ if((dirp = opendir(old_path)) == NULL){
+ return -1;
+ }
+ buf = new char[sizeof(dirent) + NAME_MAX + 1];
+
+ while(true){
+ readdir_r(dirp,(dirent*)buf,&entry);
+ if(entry == NULL){
+ break;
+ }
+ if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0){
+ continue;
+ }
+
+ if(entry->d_type == DT_DIR){
+ wait_list.push_back(entry->d_name);
+ }else{
+ old_path[old_len] = '/';
+ new_path[new_len] = '/';
+ len = strlen(entry->d_name);
+ for(i = 0;i <= len;i++){
+ old_path[old_len + i + 1] = entry->d_name[i];
+ new_path[new_len + i + 1] = entry->d_name[i];
+ }
+
+ infd = open(old_path,O_RDONLY);
+ outfd = open(new_path,O_WRONLY | O_CREAT);
+ fstat(infd,&st);
+ sendfile(outfd,infd,NULL,st.st_size);
+ close(infd);
+ close(outfd);
+
+ old_path[old_len] = '\0';
+ new_path[new_len] = '\0';
+ }
+ }
+
+ delete buf;
+ closedir(dirp);
+
+ while(!wait_list.empty()){
+ tname = wait_list.back().c_str();
+ wait_list.pop_back();
+
+ old_path[old_len] = '/';
+ new_path[new_len] = '/';
+ len = strlen(tname);
+ for(i = 0;i <= len;i++){
+ old_path[old_len + i + 1] = tname[i];
+ new_path[new_len + i + 1] = tname[i];
+ }
+
+ mkdir(new_path,0775);
+
+ copydir_travel(old_path,old_len + len + 1,new_path,new_len + len + 1);
+
+ old_path[old_len] = '\0';
+ new_path[new_len] = '\0';
+ }
+
+ return 0;
+}
+int tool_copydir(char *old_path,char *new_path){
+ char old_buf[PATH_MAX + 1];
+ char new_buf[PATH_MAX + 1];
+
+ tool_cleardir(new_path);
+ mkdir(new_path,0775);
+
+ old_buf[0] = '\0';
+ strncat(old_buf,old_path,sizeof(old_buf));
+ new_buf[0] = '\0';
+ strncat(new_buf,new_path,sizeof(new_buf));
+
+ copydir_travel(old_buf,strlen(old_buf),new_buf,strlen(new_buf));
+
+ return 0;
+}
diff --git a/judge/tool.h b/judge/tool.h
new file mode 100644
index 0000000..f876c29
--- /dev/null
+++ b/judge/tool.h
@@ -0,0 +1,26 @@
+#define PACK_BUFSIZE 65536
+struct pack_bzinfo{
+ bz_stream bzs;
+ char buf[PACK_BUFSIZE];
+ int len;
+ int off;
+ bool endflag;
+};
+
+static int pack_copenfn(const char *pathname,int flags,...);
+static int pack_cclosefn(long fd);
+static ssize_t cpack_writefn(long fd,const void *buf,size_t count);
+static int pack_xopenfn(const char *pathname,int flags,...);
+static int pack_xclosefn(long fd);
+static ssize_t pack_xreadfn(long fd,void *buf,size_t count);
+
+static std::map<int,pack_bzinfo*> pack_fdmap;
+
+int tool_pack(char *pack_path,char *dir_path);
+int tool_unpack(char *pack_path,char *dir_path);
+
+static int cleardir_callback(const char *path,const struct stat *st,int flag,struct FTW *ftw_buf);
+static int copydir_travel(char *old_path,int old_len,char *new_path,int new_len);
+
+int tool_cleardir(char *path);
+int tool_copydir(char *old_path,char *new_path);
diff --git a/judge/tpool.h b/judge/tpool.h
new file mode 100644
index 0000000..c06efc1
--- /dev/null
+++ b/judge/tpool.h
@@ -0,0 +1,175 @@
+#include<pthread.h>
+#include<semaphore.h>
+#include<sys/eventfd.h>
+#include<queue>
+#include<vector>
+
+class tpool_protofn{
+public:
+ virtual void operator()(void *data) = 0;
+};
+
+template<typename C>
+class tpool_fn : public tpool_protofn{
+private:
+ typedef void (C::*tpool_fn_type)(void *data);
+ C *obj;
+ tpool_fn_type fn;
+
+public:
+ tpool_fn(C *obj,tpool_fn_type fn){
+ this->obj = obj;
+ this->fn = fn;
+ }
+ void operator()(void *data){
+ (obj->*fn)(data);
+ }
+};
+class tpool_static_fn : public tpool_protofn{
+private:
+ typedef void (*tpool_static_fn_type)(void *data);
+ tpool_static_fn_type fn;
+
+public:
+ tpool_static_fn(tpool_static_fn_type fn){
+ this->fn = fn;
+ }
+ void operator()(void *data){
+ fn(data);
+ }
+};
+
+class tpool_thcb{
+public:
+ tpool_protofn *th_fn;
+ void *th_data;
+ tpool_protofn *cb_fn;
+ void *cb_data;
+
+ tpool_thcb(tpool_protofn *th_fn,void *th_data,tpool_protofn *cb_fn,void *cb_data){
+ this->th_fn = th_fn;
+ this->th_data = th_data;
+ this->cb_fn = cb_fn;
+ this->cb_data = cb_data;
+ }
+ int run(){
+ (*th_fn)(th_data);
+ return 0;
+ }
+ int done(){
+ if(cb_fn != NULL){
+ (*cb_fn)(cb_data);
+ }
+ return 0;
+ }
+};
+
+#define TPOOL_THREAD_MAXNUM 64
+class tpool{
+private:
+ std::queue<tpool_thcb*> wait_queue;
+ std::vector<tpool_thcb*> done_list;
+ pthread_t pt[TPOOL_THREAD_MAXNUM];
+ int pt_num;
+ sem_t pt_sem;
+ pthread_mutex_t pt_mutex;
+
+ static void* pt_runfn(void *arg){
+ tpool *that;
+ tpool_thcb *thcb;
+ long long int sig;
+
+ that = (tpool*)arg;
+
+ while(true){
+
+ sem_wait(&that->pt_sem);
+
+ pthread_mutex_lock(&that->pt_mutex);
+
+ if(!that->wait_queue.empty()){
+ thcb = that->wait_queue.front();
+ that->wait_queue.pop();
+ }else{
+ thcb = NULL;
+ }
+
+ pthread_mutex_unlock(&that->pt_mutex);
+
+ if(thcb == NULL){
+ continue;
+ }
+
+ thcb->run();
+
+ pthread_mutex_lock(&that->pt_mutex);
+
+ that->done_list.push_back(thcb);
+
+ pthread_mutex_unlock(&that->pt_mutex);
+
+ sig = 1;
+ write(that->fd,&sig,sizeof(sig)),that->done_list.size();
+ }
+ return NULL;
+ }
+
+public:
+ int fd;
+
+ tpool(int pt_num){
+ if((this->pt_num = pt_num) > TPOOL_THREAD_MAXNUM){
+ this->pt_num = TPOOL_THREAD_MAXNUM;
+ }
+ fd = eventfd(0,EFD_NONBLOCK);
+ sem_init(&pt_sem,0,0);
+ pthread_mutex_init(&pt_mutex,NULL);
+ }
+ ~tpool(){
+ close(fd);
+ sem_destroy(&pt_sem);
+ pthread_mutex_destroy(&pt_mutex);
+ }
+ int start(){
+ int i;
+
+ for(i = 0;i < pt_num;i++){
+ pthread_create(&pt[pt_num],NULL,pt_runfn,this);
+ }
+
+ return 0;
+ }
+ int done(){
+ int i;
+ std::vector<tpool_thcb*> l;
+ long long int sig;
+
+ pthread_mutex_lock(&pt_mutex);
+
+ l.swap(done_list);
+
+ pthread_mutex_unlock(&pt_mutex);
+
+ for(i = l.size() - 1;i >= 0;i--){
+ l[i]->done();
+ delete l[i];
+ }
+
+ read(fd,&sig,sizeof(sig));
+ }
+ int add(tpool_protofn *th_fn,void *th_data,tpool_protofn *cb_fn,void *cb_data){
+ tpool_thcb *thcb;
+
+ thcb = new tpool_thcb(th_fn,th_data,cb_fn,cb_data);
+
+ pthread_mutex_lock(&pt_mutex);
+
+ wait_queue.push(thcb);
+
+ pthread_mutex_unlock(&pt_mutex);
+
+ sem_post(&pt_sem);
+
+ return 0;
+ }
+};