2017-05-20 11:03:05 +02:00
package Job ;
import java.io.File ;
import java.io.FileWriter ;
import java.io.IOException ;
import java.io.RandomAccessFile ;
import java.util.ArrayList ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Scanner ;
import Comunication.Server ;
2018-04-25 18:23:03 +02:00
import Core.Program ;
2017-05-20 11:03:05 +02:00
import Utils.StringUtils ;
public class JobManager implements Iterator < Job > {
private List < Job > enqued = new ArrayList < Job > ( ) ; //enqued jobs
private List < Job > todo = new ArrayList < Job > ( ) ; //compiled jobs
2017-05-20 21:17:08 +02:00
private List < Job > send = new ArrayList < Job > ( ) ; //assigned jobs
2017-05-20 11:03:05 +02:00
private List < Job > done = new ArrayList < Job > ( ) ; //done jobs
2018-04-25 18:23:03 +02:00
private Program prog ;
2017-05-20 21:17:08 +02:00
private int jobcount = 0 ;
2017-05-20 11:03:05 +02:00
private boolean isCompiling = false ;
2018-04-25 18:23:03 +02:00
public JobManager ( Program program ) {
prog = program ;
}
2017-07-31 14:00:08 +02:00
public void reenque ( List < Job > jobs ) {
todo . addAll ( 0 , jobs ) ;
send . removeAll ( jobs ) ;
update ( ) ;
}
2018-04-25 18:23:03 +02:00
public void enque ( Job newjob , boolean isPreCompiled ) {
2017-05-21 16:24:46 +02:00
jobcount + + ;
2017-05-20 11:03:05 +02:00
newjob . setId ( jobcount ) ;
2018-04-25 18:23:03 +02:00
if ( isPreCompiled )
todo . add ( newjob ) ;
else
enqued . add ( newjob ) ;
2017-05-20 11:03:05 +02:00
update ( ) ;
}
2017-07-31 14:00:08 +02:00
/ * *
* Creates a new Compiling Thread
* @return
* /
2017-05-20 11:38:10 +02:00
private Thread getnewThread ( ) {
2017-05-20 11:03:05 +02:00
return new Thread ( new Runnable ( ) {
@Override
public void run ( ) {
isCompiling = true ; //doppelt hält besser
2018-04-25 18:23:03 +02:00
//compile them!
while ( enqued . size ( ) > 0 & & todo . size ( ) < jobs_compiledtarget ( ) & & isCompiling ) {
2017-05-20 11:03:05 +02:00
Job j = enqued . get ( 0 ) ;
2018-04-25 18:23:03 +02:00
if ( j = = null ) {
System . out . println ( " enqued.size(): " + enqued . size ( ) + " but job.get(0) is null! " ) ;
break ;
}
2017-05-20 11:03:05 +02:00
//compile script
try {
// System.out.println(j.code);
String classname = StringUtils . cutout ( j . code , " class " , " extends " ) ; //class [name] extends
File file = new File ( classname + " .java " ) ; //delete old & file creation
if ( file . exists ( ) )
file . delete ( ) ;
file . createNewFile ( ) ;
File classfile = new File ( classname + " .class " ) ; //remove class file
if ( classfile . exists ( ) )
classfile . delete ( ) ;
FileWriter fw = new FileWriter ( file ) ; //file writing
fw . write ( j . code ) ;
fw . close ( ) ;
Process process = Runtime . getRuntime ( ) . exec ( " javac " + file . getAbsolutePath ( ) ) ; //compile
Scanner scan = new Scanner ( process . getErrorStream ( ) ) ;
while ( scan . hasNextLine ( ) ) {
System . out . println ( " Compile Err: " + scan . nextLine ( ) ) ;
}
scan . close ( ) ;
process . waitFor ( ) ;
RandomAccessFile f = new RandomAccessFile ( classfile , " r " ) ;
j . classfile = new byte [ ( int ) f . length ( ) ] ;
f . read ( j . classfile ) ;
f . close ( ) ;
j . compiled = true ;
j . classname = classname ;
2018-04-27 10:29:39 +02:00
j . code = null ;
2017-05-20 11:03:05 +02:00
enqued . remove ( 0 ) ; //manage ques
todo . add ( j ) ;
if ( classfile . exists ( ) ) //delete all files
classfile . delete ( ) ;
if ( file . exists ( ) )
file . delete ( ) ;
} catch ( IOException | InterruptedException e ) {
e . printStackTrace ( ) ;
}
}
isCompiling = false ;
2018-04-25 18:23:03 +02:00
// System.out.println("Compiler stopped!");
2017-05-20 11:03:05 +02:00
}
} , " Compiler " ) ;
}
2017-07-31 14:00:08 +02:00
/ * *
* is a new Compiled job in the list
* /
2017-05-20 11:03:05 +02:00
@Override
public boolean hasNext ( ) {
2018-04-25 18:23:03 +02:00
if ( todo . size ( ) = = 0 ) {
update ( ) ;
return false ;
}
return true ;
2017-05-20 11:03:05 +02:00
}
@Override
public Job next ( ) {
2018-04-25 18:23:03 +02:00
//Warning! not checked if todo.get(0) exists!
2017-05-20 21:17:08 +02:00
send . add ( todo . get ( 0 ) ) ;
2017-05-20 11:03:05 +02:00
todo . remove ( 0 ) ;
update ( ) ;
2018-04-25 18:23:03 +02:00
System . out . println ( ( ( int ) ( ( ( float ) done . size ( ) ) / ( ( float ) jobs_total ( ) ) ) * 100 ) + " % Done " ) ;
2017-05-20 21:17:08 +02:00
return send . get ( send . size ( ) - 1 ) ;
2017-05-20 11:03:05 +02:00
}
2018-04-25 18:23:03 +02:00
/ * *
* Called , when the job - lists get modified or a new client connects .
* This method simply checks weather the compiler - thread should be started or not .
* If the Thread should be started , this method does it with no further instruction .
* /
public void update ( ) {
boolean hasnext = true ; //variable zum testen, ob das Programm weitere Jobs hat
while ( enqued . size ( ) + todo . size ( ) < jobs_compiledtarget ( ) & & ( hasnext = prog . enquenextJob ( ) ) ) ; //genarte new jobs!
if ( ! hasnext ) {
System . out . println ( " Program has no new Jobs! " ) ;
//TODO: somehow stop the compile thread after compiling (and disable it from re-opening) and set a flag, that after these jobs are done the server could shutdown.
}
if ( enqued . size ( ) > 0 & & ! isCompiling & & todo . size ( ) < jobs_compiledtarget ( ) ) { //7 jobs for each connection and at least 10
2017-05-20 11:03:05 +02:00
startCompile ( ) ;
}
}
public int jobs_done ( ) {
return done . size ( ) ;
}
2017-05-20 21:17:08 +02:00
public int jobs_send ( ) {
return send . size ( ) ;
}
2017-05-20 11:03:05 +02:00
public int jobs_compiled ( ) {
return todo . size ( ) ;
}
public int jobs_enqued ( ) {
return enqued . size ( ) ;
}
public int jobs_total ( ) {
return jobcount ;
}
2017-07-31 14:00:08 +02:00
/ * *
* How many Jobs should stored compiled ?
* @return 7 Jobs for every Connection , and at least 10 .
* /
2017-05-20 11:03:05 +02:00
public int jobs_compiledtarget ( ) {
int w = 7 * Server . getServer ( ) . getConnectionCount ( ) ;
2017-05-20 11:38:10 +02:00
return ( w < 10 ) ? 10 : w ;
2017-05-20 11:03:05 +02:00
}
private void startCompile ( ) {
if ( ! isCompiling ) {
isCompiling = true ;
getnewThread ( ) . start ( ) ;
}
}
2017-05-20 15:27:54 +02:00
2017-05-20 21:17:08 +02:00
/ * *
* Drop all jobs
* /
public void clear ( ) {
//posible bug: when the Compiler is running, an then the que is cleared, its posible that the compiler adds a job.
//work around: add a wait, or save the Thread object and wait for it
isCompiling = false ;
enqued . clear ( ) ;
done . clear ( ) ;
send . clear ( ) ;
todo . clear ( ) ;
jobcount = 0 ;
}
2017-05-20 15:27:54 +02:00
public boolean isCompiling ( ) {
return isCompiling ;
}
2017-05-20 21:17:08 +02:00
/ * *
* Mark a job as done
* @param jobId
* /
public void setdone ( int jobId ) {
2018-04-25 18:23:03 +02:00
//find job
2017-05-20 21:17:08 +02:00
Job j = null ;
int pos = - 1 ;
for ( int i = 0 ; i < send . size ( ) ; i + + ) {
if ( send . get ( i ) . getId ( ) = = jobId ) {
j = send . get ( i ) ;
pos = i ;
break ;
}
}
if ( j ! = null ) {
send . remove ( pos ) ;
done . add ( j ) ;
2018-04-27 10:29:39 +02:00
j . classfile = null ;
2018-04-25 18:23:03 +02:00
//TODO: delete old done jobs, to preverse Memory?
2017-05-20 21:17:08 +02:00
} else {
System . out . println ( " Job id " + jobId + " not found " ) ;
}
}
2017-05-20 11:03:05 +02:00
}