#!/usr/bin/perl 
use strict;
use warnings;
use DBI;#使用資料庫

#server狀態相關參數
my $ncpu = 10;#使用cpu數量
my $tcpu = 24;#系統擁有的cpu數
my $spid = $tcpu-$ncpu;#起始pid
my $epid = $tcpu-1;#終點pid
my @cpu = ($spid..$epid);#可用的CPU list
my $nport = ($ncpu)/2;#使用port數量
my @port = (53002..53001+$nport);#可用的Port list

#連接資料庫相關參數
my $db = "EMS"; #database 名稱
my $host = "localhost"; #host name
my $user = "EMS"; #資料庫帳號
my $password = "**********"; #資料庫密碼

#模擬設定相關參數
my $id;#使用者帳號
my $date;#送出模擬日期
my $status;#模擬狀態
my $stime;#開始模擬時間
my $etime;#結束模擬時間
my $range;#模擬範圍座標
my $start;#起點座標
my $end;#終點座標
my $T_light;#紅綠燈時間
my $cnum;#車輛數
my $frequency;#模擬次數
my $simtime;#模擬時間
my $speedEV;#救護車速度(km/hr)
my $speedNV;#一般車輛速度(km/hr)
my $method;#選擇的行車策略
my $way;#過濾的way tag
my $cpu1;#用來執行SUMO
my $cpu2;#用來執行NS2
my $port;#連接SUMO及NS2的port

#利用ps command監控目前使用的simlate數量
sub check{
	#初始化可以使用的CPU和port ID
	@cpu = ($spid..$epid);
	@port = (53002..53001+$nport);
	#查看目前所執行的perl程式
	my $ps = `ps aux | grep perl`;
	#取得目前simlate.pl的執行狀況
	while ($ps =~ /simulate.pl\s\S+\s\S+\s\S+\s\S+\s\S+\s\d+\s\d+\s\d+\s\d+\s\d+\s\d+\s[A-Z]+\s[a-z=]+\s(\d+)\s(\d+)\s(\d+)/g){
		print "Current using: " . $1 . " " . $2 . " " . $3 ."\n";
		#移除使用中的CPU
		if ($1 ~~ @cpu){
			@cpu = grep {$_ != $1} @cpu;
		}
		if ($2 ~~ @cpu){
			@cpu = grep {$_ != $2} @cpu;
		}
		#移除使用中的的port
		if ($3 ~~ @port){
			@port = grep {$_ != $3} @port;
		}
	}
		print "@cpu" . "\n";
		print "@port" . "\n";
}

#連結資料庫並且取得模擬參數
sub getData{
	#初始化參數
	$id = ();
	$date = ();
	$status = 0;
	$stime = ();
	$etime = ();
	$range = ();
	$start = ();
	$end = ();
	$cnum = ();
	$frequency = ();
	$simtime = ();
	$speedEV = ();
	$speedNV = ();
	$T_light = ();
	$method = ();
	$way = ();

	#連接Database 
	my $dbh = DBI->connect ("DBI:mysql:database=$db:host=$host", $user, $password) 
		or die "Can't connect to database: $DBI::errstr\n";
	
	#準備執行SQL指令
	#選取status為0且依照date欄位由小到大排序的第一筆data
	my $sth = $dbh->prepare("SELECT * FROM `Simulation` WHERE `status` = 0 ORDER BY date ASC");
	#執行SQL指令
	print $sth->execute(),"\n";

	#將資料暫存於row
	if(my @row = $sth->fetchrow_array()){
		print "@row\n";
		#結束command
		$sth->finish();

		#確認讀取的參數中status=0，才存入變數並更新status及stime
		if ($row[2] eq 0) {
			print "Save Arg...\n";
			#存入參數
			$id = $row[0];
			$row[1]=~ s/\s/-/;#把空白用-取代
			$row[1]=~ s/:/-/g;#把空白用-取代
			$date = $row[1];
			$status = $row[2];
			$stime = $row[3];
			$etime = $row[4];
			$range = $row[5];
			$row[6]=~ s/\s/,/;#把空白用,取代
			$start = $row[6];
			$row[7]=~ s/\s/,/;#把空白用,取代
			$end = $row[7];
			$cnum = $row[8];
			$frequency = $row[9];
			$simtime = $row[10];
			$speedEV = $row[11];
			$speedNV = $row[12];
			$T_light = $row[13];
			$method = $row[14];
			$way = $row[15];

			#更新模擬狀態以及開始模擬時間
			$sth = $dbh->prepare("UPDATE `Simulation` SET `status` = '1', `stime` = NOW() WHERE `ID` = '$id'  AND `date` = '$date'");
			$status = 1;
			#執行SQL指令
			$sth->execute();
			#結束command
			$sth->finish();
		}

		#中斷資料庫連結
		$dbh->disconnect or warn "Disconnection error: $DBI::errstr\n";
	}
}

while (1) {
	#取得目前可以使用的cpu id以及port id
	&check;

	#執行一次模擬需要2個cpu以及1個port
	if (@cpu>=2 or @port>=1){
		#取得使用者模擬設定
		&getData;

		#執行模擬
		if ($status eq 1) {
			print "Start Simulation!\n";
			#放入背景執行
			print "bash -c \"perl simulate.pl $id $date $range $start $end $T_light $cnum $frequency $simtime $speedEV $speedNV $method $way $cpu[@cpu-1] $cpu[@cpu-2] $port[@port-1] &>/dev/null &\"\n";

			system "bash -c \"perl simulate.pl $id $date $range $start $end $T_light $cnum $frequency $simtime $speedEV $speedNV $method $way $cpu[@cpu-1] $cpu[@cpu-2] $port[@port-1] &>/dev/null &\"";
		}
	}

	#休息10秒後重新啟動
	sleep (10);
}
