📄 ojserver.c
字号:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#include <sys/wait.h>
#include "/usr/include/mysql/mysql.h"
//#include "config.h"
#define RF -996
#define CE -997
#define Compiling -998
#define SIGRUNNING -999
#define SIGWA -1000
#define SIGOLE -1001
#define SIGAC -1002
#define SIGPE -1003
#define SIGTLE 24
MYSQL mysql;
char Author[50];
int Exeid;
int QuerryDB();
int Compile(int Runid);
int Run(int Runid);
// Deal with TLE that give up the usage of CPU
pid_t TLEPID;
int TLERunid,TLETimelimit;
int WriteMysql(int Runid,int status,float passtime,int mem)
{
char tmp[200];
sprintf(tmp,"update Status set Judgestatus =%d ,Runtime =%f ,Memory =%d where Runid=%d;",status,passtime,mem,Runid);
// printf("%s\n",tmp);
mysql_query(&mysql,tmp);
return 0;
}
void TLEHANDLER(int i)
{
int status;
rusage TLEUsage;
kill(TLEPID,9);
wait(&status);
getrusage(RUSAGE_CHILDREN, &TLEUsage);
WriteMysql(TLERunid,24,TLETimelimit,TLEUsage.ru_minflt*4);
exit(24);
}
int main(int argc, char **argv)
{
mysql_init(&mysql);
mysql_connect(&mysql,"localhost","root","pwd");
int Runid=QuerryDB();
if(Runid==-1)
return -1;
if(Compile(Runid)==-1)
return -1;
Run(Runid);
mysql_close(&mysql);
return 0;
}
int QuerryDB()
{
mysql_select_db(&mysql,"OJS");
char tmp[200];
int Runid;
sprintf(tmp,"select * from Queue order by Runid asc;");
MYSQL_RES *res;
MYSQL_ROW row;
mysql_query(&mysql,tmp);
res = mysql_store_result(&mysql);
row = mysql_fetch_row(res);
if(row==NULL)
return -1;
sscanf(row[0],"%d",&Runid);
mysql_free_result(res);
sprintf(tmp,"delete from Queue where Runid=%d;",Runid);
if(mysql_query(&mysql,tmp)==0)
{
return Runid;
}
return -1;
}
int Compile(int Runid)
{
char tmp[200];
int Proid;
MYSQL_RES *res;
MYSQL_ROW row;
sprintf(tmp,"select * from Status where Runid=%d;",Runid);
mysql_query(&mysql,tmp);
res = mysql_store_result(&mysql);
row = mysql_fetch_row(res);
if(row==NULL)
{
fprintf(stderr,"Wrong Runid !\n");
return 0;
}
sscanf(row[1],"%d",&Proid);
sscanf(row[6],"%s",Author);
mysql_free_result(res);
sprintf(tmp,"update Problems set Totalsubmit =Totalsubmit+1 where Proid=%d;",Proid);
mysql_query(&mysql,tmp);
sprintf(tmp,"Update Users set Totalsubmit=Totalsubmit+1 where Name=\"%s\";",Author);
mysql_query(&mysql,tmp);
sprintf(tmp,"update Status set Judgestatus =-998 where Runid=%d;",Runid);
mysql_query(&mysql,tmp);
Exeid=rand()%1000;
sprintf(tmp,"g++ /acm/ojs/tmp/%d.cpp -o /acm/ojs/tmp/%d -ansi -fno-asm -Wall -lm -DONLINE_JUDGE --static 2> /acm/ojs/err/%d.txt",Runid,Exeid,Runid);
if(system(tmp)!=0)
{
sprintf(tmp,"update Status set Judgestatus =-997 where Runid=%d;",Runid);
mysql_query(&mysql,tmp);
return -1;
}
sprintf(tmp,"g++ /acm/ojs/tmp/RF%d.cpp -o /acm/ojs/tmp/RF%d -ansi -fno-asm -Wall -lm -DONLINE_JUDGE --static 2> /acm/ojs/err/%d.txt",Runid,Exeid,Runid);
if(system(tmp)!=0)
{
sprintf(tmp,"update Status set Judgestatus =-996 where Runid=%d;",Runid);
mysql_query(&mysql,tmp);
return -1;
}
sprintf(tmp,"rm -f /acm/ojs/err/%d.txt",Runid);
system(tmp);
return 0;
}
bool IsIdentified(char a)
{
if(a=='\n'||a=='\t'||a=='\b'||a==' ')
return false;
return true;
}
int Run(int Runid) // Exe is Exeid, find Problem information from Runid
{
MYSQL_RES *res;
MYSQL_ROW row;
int Timelimit,Memlimit,Proid;
rlimit memlim,timlim;
char tmp[200];
// Find Proid
sprintf(tmp,"select * from Status where Runid=%d;",Runid);
mysql_query(&mysql,tmp);
res = mysql_store_result(&mysql);
row = mysql_fetch_row(res);
if(row==NULL)
{
fprintf(stderr,"Wrong Runid !\n");
return 0;
}
sscanf(row[1],"%d",&Proid);
mysql_free_result(res);
//Find Limit
sprintf(tmp,"select * from Problems where Proid=%d;",Proid);
mysql_query(&mysql,tmp);
res = mysql_store_result(&mysql);
row = mysql_fetch_row(res);
sscanf(row[1],"%d",&Timelimit); // Time limit is measured by seconds
sscanf(row[2],"%d",&Memlimit); // Memory limit is measured by Megabytes;
Memlimit=Memlimit+1;
mysql_free_result(res);
// Time limit & Memory limit
memlim.rlim_cur=Memlimit*1024*1024;
timlim.rlim_cur=Timelimit;
//Running
sprintf(tmp,"update Status set Judgestatus =-999 where Runid=%d;",Runid);
mysql_query(&mysql,tmp);
if(fork()!=0)
{
int wt;
waitpid(0,&wt,0);
return 0;
}
int pipefds[2];
pipe(pipefds);
pid_t pid=fork();
if(pid==0) //Children
{
char tmp[100];
sprintf(tmp,"/acm/ojs/data/%d.in",Proid);
freopen(tmp,"r",stdin);
close(1);
dup(pipefds[1]);
close(pipefds[0]);
close(pipefds[1]);
setrlimit( RLIMIT_CPU,&timlim);
setrlimit( RLIMIT_AS,&memlim);
sprintf(tmp,"/%d",Exeid);
char tmp2[100];
sprintf(tmp2,"./%d",Exeid);
chroot("/acm/ojs/tmp/");
setuid(99);
setgid(99);
execlp(tmp,tmp2,NULL);
return 0;
}
int status;
bool WA=false,AC=false,PE=false;
bool Fend=false,Pend=false;
rusage usage;
close(0);
dup(pipefds[0]);
close(pipefds[0]);
close(pipefds[1]);
FILE *p;
char path[50];
sprintf(path,"/acm/ojs/data/%d.out",Proid);
p=fopen(path,"r");
char Petmp[1000],Ftmp[1000];
bool ACenable=true;
// Deal with TLE that give up the usage of CPU
TLERunid=Runid;
TLEPID=pid;
TLETimelimit=Timelimit;
alarm(TLETimelimit);
signal(SIGALRM,&TLEHANDLER);
while(true)
{
char a,b;
if(fscanf(p,"%c",&a)==EOF)
{ a=' '; Fend=true; }
if(scanf("%c",&b)==EOF)
{ b=' '; Pend=true; }
if(Fend&&Pend)
{
if(ACenable)
AC=true;
else PE=true;
break;
}
if(a!=b)
{
ACenable=false;
if( IsIdentified(a)&&IsIdentified(b) )
{
WA=true;
kill(pid,9);
break;
}
if( IsIdentified(a))
{
while(true)
{
if(scanf("%c",&b)==EOF)
{ Pend=true; WA=true; break; }
if(IsIdentified(b))
break;
}
if(Pend)
break;
if(a==b)
continue;
else { WA=true; kill(pid,9); break; }
}
else if(IsIdentified(b))
{
while(true)
{ if(fscanf(p,"%c",&a)==EOF)
{ Fend=true; WA=true; break; }
if(IsIdentified(a))
break;
}
if(Fend)
break;
if(a==b)
continue;
else { WA=true; kill(pid,9); break; }
}
}
}
wait(&status);
getrusage(RUSAGE_CHILDREN, &usage);
// printf("status === %d\n",status);
float passtime;
passtime=usage.ru_utime.tv_sec+usage.ru_stime.tv_sec+(float)(usage.ru_stime.tv_usec+usage.ru_utime.tv_usec)/1000000;
if(passtime>Timelimit)
status=24;
if(usage.ru_minflt*4>(Memlimit-1)*1024)
status=6;
if(status==24 || status==11 ||status==8 || status==6 )
{
if(status==6 && usage.ru_minflt*4 < (Memlimit-1)*1024 )
usage.ru_minflt= Memlimit*1024/4;
WriteMysql(Runid,status,passtime,usage.ru_minflt*4);
return 0;
}
if(AC)
{
WriteMysql(Runid,SIGAC,passtime,usage.ru_minflt*4);
sprintf(tmp,"update Problems set Accepted=Accepted+1 where Proid=%d;",Proid);
mysql_query(&mysql,tmp);
sprintf(tmp,"select * from Acs where Proid=%d and Author=\"%s\";",Proid,Author);
mysql_query(&mysql,tmp);
res = mysql_store_result(&mysql);
row = mysql_fetch_row(res);
if(row==NULL)
{
sprintf(tmp,"insert into Acs values(-100,%d,\"Undifined\",1002,%lf,%d,\"%s\");",Proid,passtime,usage.ru_minflt*4,Author);
mysql_query(&mysql,tmp);
sprintf(tmp,"update Users set Accepted=Accepted+1 where Name=\"%s\";",Author);
mysql_query(&mysql,tmp);
sprintf(tmp,"cp -f /acm/ojs/tmp/%d.cpp /acm/ojs/src/%s.%d",Runid,Author,Proid);
system(tmp);
}
else
{
float Actime;
int Acmemory;
sscanf(row[4],"%f",&Actime);
sscanf(row[5],"%d",&Acmemory);
bool upd=false;
if(Actime>passtime)
upd=true;
if(Actime==passtime && Acmemory > usage.ru_minflt*4 )
upd=true;
sprintf(tmp,"/acm/ojs/src/%s.%d",Author,Proid);
if(access(tmp,F_OK)!=0)
upd = true;
if(upd)
{
sprintf(tmp,"update Acs set Runtime=%f,Memory=%d where Proid=%d and Author=\"%s\";",passtime,usage.ru_minflt*4,Proid,Author);
mysql_query(&mysql,tmp);
sprintf(tmp,"cp -f /acm/ojs/tmp/%d.cpp /acm/ojs/src/%s.%d",Runid,Author,Proid);
system(tmp);
}
return 0;
}
}
if(PE)
{
WriteMysql(Runid,SIGPE,passtime,usage.ru_minflt*4);
return 0;
}
if(WA)
{
WriteMysql(Runid,SIGWA,passtime,usage.ru_minflt*4);
return 0;
}
if(status)
{
WriteMysql(Runid,status,passtime,usage.ru_minflt*4);
return 0;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -