blob: 1893f442db1b405c1fc36eaff0cc50ce316eb8f4 [file] [log] [blame]
#include "server_conn.h"
struct Judger_data {
int runid;
Judger_data * next;
};
struct ARG {
int num;
int fd;
};
bool portreuse[70000]={false};
Judger_data *head,*tail;
bool thread_busy[MAX_JUDGER_NUMBER];
bool used[MAX_JUDGER_NUMBER];
int temp_num;
int queuesize;
pthread_mutex_t mutex_link=PTHREAD_MUTEX_INITIALIZER;
void writelog(char * templog)
{
FILE *fp=fopen(logfile,"a");
if (fp!=NULL) {
fprintf(fp,"%s",templog);
fclose(fp);
}
}
void result_dealer(char filename[200],int temp_pid,int temp_runid,int temp_cid,char temp_username[])
{
MYSQL * mysql;
MYSQL_RES *res;
MYSQL_ROW row;
mysql=(MYSQL *)malloc(sizeof(MYSQL));
mysql_init(mysql);
if (!mysql_real_connect(mysql,NULL,db_user,db_pass,db_table,MYSQL_PORT,NULL,0)) {
perror("cannot connect mysql!\n");
exit(1);
}
mysql_query(mysql,"set names utf8");
FILE *target_file=fopen(filename,"r");
int type,ri,mu,tu;
char resu[1000]={0};
char ts[10][50];
fscanf(target_file,"%s %d\n%s %d\n%s %d\n%s %d\n%s ",ts[0],&type,ts[1],&ri,ts[2],&mu,ts[3],&tu,ts[4]);
fgets(resu,1000,target_file);
char update[2000]={0};
sprintf(update,"SELECT username,contest_belong,pid FROM status WHERE runid=%d",ri);
mysql_query(mysql,update);
res=mysql_use_result(mysql);
row=mysql_fetch_row(res);
temp_runid=ri;
strcpy(temp_username,row[0]);
temp_cid=atoi(row[1]);
temp_pid=atoi(row[2]);
mysql_free_result(res);
resu[strlen(resu)-1]=0;
sprintf(update,"UPDATE status set result='%s', memory_used=%d, time_used=%d WHERE runid=%d",resu,mu,tu,ri);
mysql_query(mysql,update);
if (strcmp(resu,"Accepted")==0) {
sprintf(update,"SELECT count(*) FROM status WHERE username='%s' AND pid='%d' AND result='Accepted'",temp_username,temp_pid);
mysql_query(mysql,update);
res=mysql_use_result(mysql);
row=mysql_fetch_row(res);
if (atoi(row[0])==1) {
mysql_free_result(res);
sprintf(update,"UPDATE user set total_ac=total_ac+1 WHERE username='%s'",temp_username);
mysql_query(mysql,update);
res=mysql_use_result(mysql);
}
mysql_free_result(res);
sprintf(update,"UPDATE problem set total_ac=total_ac+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Wrong Answer")==0) {
sprintf(update,"UPDATE problem set total_wa=total_wa+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Runtime Error")==0) {
sprintf(update,"UPDATE problem set total_re=total_re+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Presentation Error")==0) {
sprintf(update,"UPDATE problem set total_pe=total_pe+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Time Limit Exceed")==0) {
sprintf(update,"UPDATE problem set total_tle=total_tle+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Memory Limit Exceed")==0) {
sprintf(update,"UPDATE problem set total_mle=total_mle+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Output Limit Exceed")==0) {
sprintf(update,"UPDATE problem set total_ole=total_ole+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Restricted Function")==0) {
sprintf(update,"UPDATE problem set total_rf=total_rf+1 WHERE pid=%d",temp_pid);
}
else if (strcmp(resu,"Compile Error")==0) {
char tempce[500]={0};
char ce_info_data[MAX_DATA_SIZE]={0};
char ceupdate[MAX_DATA_SIZE]={0};
fgets(tempce,500,target_file);
while (1) {
fgets(tempce,500,target_file);
if (strcmp(tempce,"__COMPILE-INFO-END-LABLE__")==0||strcmp(tempce,"__COMPILE-INFO-END-LABLE__\n")==0) break;
strcat(ce_info_data,tempce);
}
std::string str1;
str1=ce_info_data;
int lastpos=0;
while (str1.find("\"",lastpos,1)!=std::string::npos) {
lastpos=str1.find("\"",lastpos,1);
str1.replace(lastpos,1,"\\\"");
lastpos+=2;
}
strcpy(ce_info_data,str1.c_str());
sprintf(ceupdate,"UPDATE status set ce_info=\"%s\" WHERE runid=%d",ce_info_data,ri);
mysql_query(mysql,ceupdate);
sprintf(update,"UPDATE problem set total_ce=total_ce+1 WHERE pid=%d",temp_pid);
}
mysql_query(mysql,update);
char templog[2000]={0};
sprintf(templog,"Received a result, user: %s, runid: %d result:%s\n",temp_username,temp_runid,resu);
writelog(templog);
fclose(target_file);
mysql_close(mysql);
free(mysql);
}
void judger_thread(ARG* arg)
{
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL * mysql;
char buffer[MAX_DATA_SIZE]={0};
while (1)
{
usleep(5000);
if (thread_busy[arg->num]) {
mysql=(MYSQL *)malloc(sizeof(MYSQL));
mysql_init(mysql);
if (!mysql_real_connect(mysql,NULL,db_user,db_pass,db_table,MYSQL_PORT,NULL,0)) {
perror("cannot connect mysql!\n");
exit(1);
}
mysql_query(mysql,"set names utf8");
queuesize--;
pthread_mutex_lock(&mutex_link);
if (head==NULL) {
thread_busy[arg->num]=false;
pthread_mutex_unlock(&mutex_link);
continue;
}
Judger_data *temp=head;
head=head->next;
if (temp==tail) tail=NULL;
pthread_mutex_unlock(&mutex_link);
char query[200]={0};
sprintf(query,"SELECT source,runid,language,pid FROM status WHERE runid=%d",temp->runid);
int temp_t=mysql_real_query(mysql,query,strlen(query));
if (temp_t) {
perror("mysql query error!");
exit(1);
}
res=mysql_use_result(mysql);
row=mysql_fetch_row(res);
char filename[50]={0};
sprintf(filename,"raw_files/%d.bott",temp->runid);
FILE* datafile=fopen(filename,"w");
fprintf(datafile,"<type> 2\n");
fprintf(datafile,"__SOURCE-CODE-BEGIN-LABLE__\n");
fprintf(datafile,"%s\n",row[0]);
fprintf(datafile,"__SOURCE-CODE-END-LABLE__\n");
fprintf(datafile,"<runid> %s\n<language> %s\n<pid> %s\n",row[1],row[2],row[3]);
int temp_pid=atoi(row[3]);
mysql_free_result(res);
sprintf(query,"SELECT number_of_testcase,time_limit,case_time_limit,memory_limit,special_judge_status FROM problem WHERE pid=%d",temp_pid);
temp_t=mysql_real_query(mysql,query,strlen(query));
if (temp_t) {
perror("mysql query error!");
exit(1);
}
res=mysql_use_result(mysql);
row=mysql_fetch_row(res);
fprintf(datafile,"<testcases> %s\n<time_limit> %s\n<case_limit> %s\n<memory_limit> %s\n<special> %s\n",row[0],row[1],row[2],row[3],row[4]);
mysql_free_result(res);
sprintf(query,"UPDATE status set result='Judging' WHERE runid=%d",temp->runid);
mysql_real_query(mysql,query,strlen(query));
fclose(datafile);
int source=open(filename,O_RDONLY);
while((temp_t=read(source,buffer,sizeof(buffer)))>0)
write(arg->fd,buffer,temp_t);
close(source);
sprintf(filename,"results/%dres.bott",temp->runid);
FILE *target_file=fopen(filename,"w");
bool got_things=false;
memset(buffer,0,sizeof(buffer));
while (!got_things)
{
while ((temp_t=recv(arg->fd,buffer,MAX_DATA_SIZE,MSG_DONTWAIT))>0)
{
got_things=true;
fputs(buffer,target_file);
}
if (temp_t==0) {
fclose(target_file);
char templog[200]={0};
sprintf(templog,"Lost connection with judger %d.\n",arg->num);
writelog(templog);
sprintf(templog,"Runid: %d requeued.\n",temp->runid);
writelog(templog);
sprintf(query,"UPDATE status set result='Waiting' WHERE runid=%d",temp->runid);
mysql_real_query(mysql,query,strlen(query));
temp->next=head;
if (tail==NULL) tail=temp;
head=temp;
mysql_close(mysql);
free(mysql);
return;
}
usleep(5000);
}
fclose(target_file);
int temp_runid;
char temp1[50],temp2[50],temp3[50];
sscanf(buffer,"%s%s%s%d",temp1,temp2,temp3,&temp_runid);
sprintf(filename,"results/%dres.bott",temp_runid);
target_file=fopen(filename,"w");
fputs(buffer,target_file);
while (recv(arg->fd,buffer,MAX_DATA_SIZE,MSG_DONTWAIT)>0)
fputs(buffer,target_file);
fclose(target_file);
sprintf(query,"SELECT pid,contest_belong,username FROM status WHERE runid=%d",temp->runid);
temp_t=mysql_real_query(mysql,query,strlen(query));
if (temp_t) {
perror("mysql query error!");
exit(1);
}
res=mysql_use_result(mysql);
row=mysql_fetch_row(res);
temp_pid=atoi(row[0]);
int temp_cid=atoi(row[1]);
char temp_username[256]={0};
strcpy(temp_username,row[2]);
mysql_free_result(res);
result_dealer(filename,temp_pid,temp->runid,temp_cid,temp_username);
thread_busy[arg->num]=false;
free(temp);
mysql_close(mysql);
free(mysql);
}
else {
int alive=recv(arg->fd,buffer,MAX_DATA_SIZE,MSG_DONTWAIT);
if (alive==0) {
char templog[200]={0};
sprintf(templog,"Lost connection with judger %d.\n",arg->num);
writelog(templog);
return;
}
if (alive>0) {
mysql=(MYSQL *)malloc(sizeof(MYSQL));
mysql_init(mysql);
if (!mysql_real_connect(mysql,NULL,db_user,db_pass,db_table,MYSQL_PORT,NULL,0)) {
perror("cannot connect mysql!\n");
exit(1);
}
mysql_query(mysql,"set names utf8");
int temp_runid;
char temp1[50],temp2[50],temp3[50];
sscanf(buffer,"%s%s%s%d",temp1,temp2,temp3,&temp_runid);
char filename[200]={0};
sprintf(filename,"results/%dres.bott",temp_runid);
FILE *target_file=fopen(filename,"w");
fputs(buffer,target_file);
while (recv(arg->fd,buffer,MAX_DATA_SIZE,MSG_DONTWAIT)>0)
fputs(buffer,target_file);
fclose(target_file);
char query[200]={0};
sprintf(query,"SELECT pid,contest_belong,username FROM status WHERE runid=%d",temp_runid);
int temp_t=mysql_real_query(mysql,query,strlen(query));
if (temp_t) {
perror("mysql query error!");
exit(1);
}
res=mysql_use_result(mysql);
row=mysql_fetch_row(res);
int temp_pid=atoi(row[0]);
int temp_cid=atoi(row[1]);
char temp_username[256]={0};
strcpy(temp_username,row[2]);
mysql_free_result(res);
result_dealer(filename,temp_pid,temp_runid,temp_cid,temp_username);
mysql_close(mysql);
free(mysql);
}
}
}
}
void * function (void * arg)
{
int fd=((ARG *)arg)->fd;
int tnum=((ARG *)arg)->num;
char buffer[255]={0};
thread_busy[tnum]=true;
struct timeval case_startv,case_nowv;
struct timezone case_startz,case_nowz;
gettimeofday(&case_startv,&case_startz);
int time_passed;
while (1)
{
usleep(10000);
gettimeofday(&case_nowv,&case_nowz);
time_passed=(case_nowv.tv_sec-case_startv.tv_sec)*1000+(case_nowv.tv_usec-case_startv.tv_usec)/1000;
if (recv(fd,buffer,255,MSG_DONTWAIT)>0||time_passed>5000) break;
}
char connect_type[50]={0};
sscanf(buffer,"%s",connect_type);
//printf("current fd:%d\n",fd);
if (strcmp(connect_type,submit_string)==0) {
int runid;
sscanf(buffer,"%s%d",connect_type,&runid);
char templog[200]={0};
sprintf(templog,"received a submit, runid: %d\n",runid);
writelog(templog);
Judger_data *temp;
temp=new Judger_data;
temp->runid=runid;
temp->next=NULL;
pthread_mutex_lock(&mutex_link);
if (tail!=NULL) tail->next=temp;
tail=temp;
if (head==NULL) head=temp;
pthread_mutex_unlock(&mutex_link);
queuesize++;
}
else if (strcmp(connect_type,judger_string)==0) {
char templog[200]={0};
sprintf(templog,"judger %d connected. \n",tnum);
writelog(templog);
thread_busy[tnum]=false;
judger_thread((ARG*) arg);
}
else if (strcmp(connect_type,rejudge_string)==0) {
int repid,recid;
sscanf(buffer,"%s%d%d",connect_type,&repid,&recid);
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL * mysql;
mysql=(MYSQL *)malloc(sizeof(MYSQL));
mysql_init(mysql);
if (!mysql_real_connect(mysql,NULL,db_user,db_pass,db_table,MYSQL_PORT,NULL,0)) {
perror("cannot connect mysql!\n");
exit(1);
}
mysql_query(mysql,"set names utf8");
char query[200]={0};
sprintf(query,"SELECT runid FROM status WHERE result='Rejudging' and contest_belong=%d and pid=%d order by runid",recid,repid);
mysql_query(mysql,query);
res=mysql_use_result(mysql);
int rejudge_num=0;
pthread_mutex_lock(&mutex_link);
while ((row=mysql_fetch_row(res)))
{
rejudge_num++;
Judger_data *temp;
temp=new Judger_data;
temp->runid=atoi(row[0]);
temp->next=NULL;
if (tail!=NULL) tail->next=temp;
tail=temp;
if (head==NULL) head=temp;
}
pthread_mutex_unlock(&mutex_link);
char templog[200]={0};
sprintf(templog,"received a rejudge request, pid: %d, cid: %d, num: %d\n",repid,recid,rejudge_num);
writelog(templog);
mysql_free_result(res);
mysql_close(mysql);
free(mysql);
}
else {
writelog("Illegal connection!\nServer Recieved:\n");
writelog(buffer);
writelog("\n");
}
close(fd);
//printf("fd after close:%d\n",fd);
free(arg);
pthread_detach(pthread_self());
used[tnum]=false;
thread_busy[tnum]=false;
pthread_exit(NULL);
}
void * fetcher(void * arg)
{
while (1) {
usleep(5000);
pthread_mutex_lock(&mutex_link);
if (head==NULL) {
pthread_mutex_unlock(&mutex_link);
//printf("Empty queue.\n");
continue;
}
pthread_mutex_unlock(&mutex_link);
//printf("Not empty queue.\n");
for (int i=0;i<MAX_JUDGER_NUMBER;i++) {
if (!thread_busy[i]&&used[i]) {
thread_busy[i]=true;
break;
}
}
}
}
int main(int argc, char * argv[])
{
init();
mkdir("raw_files",0777);
mkdir("results",0777);
pthread_t tid;
ARG *arg;
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL * mysql;
int sockfd, client_fd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket() error\n");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(server_port);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd, (struct sockaddr *) & my_addr, sizeof (struct sockaddr)) == -1) {
perror("bind() error\n");
exit(1);
}
if (listen(sockfd, 10) == -1) {
perror("listen() error\n");
exit(1);
}
socklen_t sin_size = sizeof (struct sockaddr_in);
mysql=(MYSQL *)malloc(sizeof(MYSQL));
mysql_init(mysql);
if (!mysql_real_connect(mysql,NULL,db_user,db_pass,db_table,MYSQL_PORT,NULL,0)) {
perror("cannot connect mysql!\n");
exit(1);
}
mysql_query(mysql,"set names utf8");
char query[200]={0};
if (argc>1&&strcmp(argv[1],"sj")==0) {
sprintf(query,"SELECT runid FROM status WHERE result='Waiting' or result='Judging' order by runid");
}
else {
sprintf(query,"SELECT runid FROM status WHERE result='Waiting' order by runid");
}
int temp_t=mysql_real_query(mysql,query,strlen(query));
if (temp_t) {
perror("cannot query mysql!\n");
exit(1);
}
res=mysql_use_result(mysql);
while ((row=mysql_fetch_row(res)))
{
Judger_data *temp;
temp=new Judger_data;
temp->runid=atoi(row[0]);
temp->next=NULL;
if (tail!=NULL) tail->next=temp;
tail=temp;
if (head==NULL) head=temp;
}
mysql_free_result(res);
mysql_close(mysql);
free(mysql);
/*struct rlimit file_limit;
getrlimit(RLIMIT_NOFILE,&file_limit);
printf("%d %d\n",(int)file_limit.rlim_cur,(int)file_limit.rlim_max);
file_limit.rlim_cur=file_limit.rlim_max=10240;
setrlimit(RLIMIT_NOFILE,&file_limit);
getrlimit(RLIMIT_NOFILE,&file_limit);
printf("%d %d\n",(int)file_limit.rlim_cur,(int)file_limit.rlim_max);*/
pthread_create(&tid,NULL,fetcher,NULL);
while (1)
{
if ((client_fd = accept(sockfd, (struct sockaddr *) & remote_addr, &sin_size)) == -1) {
perror("accept() error");
exit(1);
}
char templog[200]={0};
sprintf(templog,"received a connection from %s:%d\n", inet_ntoa(remote_addr.sin_addr), remote_addr.sin_port);
writelog(templog);
/*if (portreuse[remote_addr.sin_port]) printf("port reused.\n");
else {
printf("port newly used.\n");
portreuse[remote_addr.sin_port]=true;
}*/
arg=new ARG;
arg->fd=client_fd;
for (temp_num=0;temp_num<MAX_JUDGER_NUMBER;temp_num++) if (!used[temp_num]) break;
arg->num=temp_num;
used[temp_num]=true;
pthread_create(&tid,NULL,function,(void *)arg);
/*if (head==NULL) continue;
for (int i=0;i<MAX_JUDGER_NUMBER;i++) {
if (!thread_busy[i]&&used[i]) {
thread_busy[i]=true;
break;
}
}*/
}
close(sockfd);
exit(0);
}