class MetaScheduler(object):
    """
    This class is the common interface between the User, Predictor and Site Scheduler
    Tasks:
     - Accept job inputs from user
     - Obtain predictions
     - Submit jobs to scheduler
     - Provide feedback (if necessary) to user and predictor
    """

    def __init__(self, jobs, num_processors, scheduler):
        
        self.num_processors = num_processors
        self.jobs = jobs
        self.do_pred = 0
        #print "inside init of metascheduler"
	#print "jobs",jobs
        #print len(self.jobs)
        
        self.terminated_jobs=[]
        self.scheduler = scheduler
        self.time_of_last_job_submission = 0
        self.event_queue = EventQueue()
       
	#with open('/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/prediction/prediction_time/files/tyrone_new_log') as f:
	with open('/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/prediction/history_log_creation/history_log.swf') as f:
           a = sum(1 for _ in f)
        #print "value of history:",a
        self.historySetSize = a-1
        
        #self.historySetSize = 0
         
        self.currentSubmitCount = 0

	if EnabledWaitPred:
            self.waitTimePredictor = WaitPredictor()
	else:
            self.waitTimePredictor = None

        if EnabledRunPred:
            self.runTimePredictor = RunPredictor()
	    
        else:
            self.runTimePredictor = None

        self.machine = ValidatingMachine(num_processors=num_processors, event_queue=self.event_queue, wait_predictor=self.waitTimePredictor, run_predictor = self.runTimePredictor, scheduler = self.scheduler)

        self.event_queue.add_handler(JobSubmissionEvent, self.handle_submission_event)
        self.event_queue.add_handler(JobTerminationEvent, self.handle_termination_event)
        
        if isinstance(scheduler, EasyPlusPlusScheduler) or isinstance(scheduler, ShrinkingEasyScheduler):
            self.event_queue.add_handler(JobPredictionIsOverEvent, self.handle_prediction_event)
        
        countSubmissions = 0    
        for job in self.jobs:
            countSubmissions += 1
            self.event_queue.add_event( JobSubmissionEvent(job.submit_time, job) )     
        #print '** Added', countSubmissions, 'job submission events to event queue **'
        self.queueSimulator = Simulator(jobs, num_processors, scheduler, self.event_queue, self.machine, )

    def modify_job_attributes(self, event, newRequestSize, actual_runtime, actual_ert):
	    #print "modify_job_attributes"
	    oldRunTime = event.job.actual_run_time
	    event.job.num_required_processors = newRequestSize
	    event.job.user_estimated_run_time = actual_ert
	    event.job.predicted_run_time = actual_ert
	    if actual_runtime == 0:
		event.job.actual_run_time = actual_ert
	    else:
                event.job.actual_run_time = actual_runtime
           

    def change_job_attributes(self, event, newRequestSize,actual_ert):
	    #print "change job attributes"
            oldRunTime = event.job.actual_run_time
	    event.job.num_required_processors = newRequestSize
	    #event.job.user_estimated_run_time = actual_ert
	    #event.job.predicted_run_time = actual_ert
	    

    def decision_metrics(self, event,queuedJobs,runningJobIDs,allrunningjobevents,jobtarrun):
        #print "inside decision metrics"
        #print "event:",event
	
       
        #queuedJobIDs = [j.id for j in self.event_queue.QueuedJobs]
        #runningJobIDs = [j.id for j in self.event_queue.RunningJobs]
        #queuedJobIDs.append(event.job.id)
       
        originalRequestSize = event.job.num_required_processors
        waitPredictions = {}
        responsePredictions = {}
	waittime_list = []
        run_list = []
        wait_list = []
        submittime = []
        #terminateval = []
	ifcounter = 0
        if EnabledRunPred:
            run_list.append(jobtarrun)
            submittime.append(event.job.submit_time)
            waitPredictions = self.waitTimePredictor.get_prediction(event.job)
            wait_list.append(waitPredictions)
            pred_run,runid = self.runTimePredictor.get_predictiondelay(event.job)
            
            
            if(len(runid) > 1):
             
             for i in runid:
              ifcounter += 1
              
              for obj in allrunningjobevents:
             	 if obj.id == i in runningJobIDs:
                       terminateval = obj
              
              runningJobIDs.remove(i)
            
              relevantRunningObjs = []
              
	      for obj in allrunningjobevents:
             	 if obj.id in runningJobIDs:
	             relevantRunningObjs.append(obj)
             
              self.runTimePredictor.notify_job_termination_event(terminateval)
              
               
              if EnabledWaitPred:
                    
                    self.waitTimePredictor.notify_arrival_event(event.job, queuedJobs, relevantRunningObjs) 
                    self.runTimePredictor.notify_arrival_event(event.job, queuedJobs, relevantRunningObjs)
                    #if self.currentSubmitCount > self.historySetSize:
                    #print "afterifcondition:"
                    #print "counter:",ifcounter
                    waitPredictions = self.waitTimePredictor.get_prediction(event.job)#to obtain waittime prediction for all running jobs
                    wait_list.append(waitPredictions)
                    #print "wait_prediction:",waitPredictions
                    RunPredictions  = self.runTimePredictor.get_actprediction(event.job)#to obtain runtime prediction for all running jobs
                    #print "run_prediction:",RunPredictions
                    run_list.append(RunPredictions)
                    submittime.append(event.job.submit_time+RunPredictions)
                 
                    runningJobIDs.append(i)
                
             delay = [];decision_list = []
             if( len(wait_list) != [] and len(wait_list) != []):
              l = submittime[0]
              for ru in range(len(run_list)):
                delay.append(abs(l-submittime[ru]))
              
              for k in range(len(wait_list)):
                decision_list.append(wait_list[k]+run_list[k]+delay[k])
              #print "eventjob:",event.job.id
              cjob = event.job.id
              runid.insert(0,cjob)
              inmade = decision_list.index(min(decision_list))
              
              return runid,cjob,runid[inmade],inmade,delay
             else:
              empty = []
              return empty,event.job.id,event.job.id,1,empty
            else:
              empty = []
              return empty,event.job.id,event.job.id,1,empty
#study from here

    def handle_submission_event(self, event):
        assert isinstance(event, JobSubmissionEvent)
        self.currentSubmitCount += 1
        queuedJobs = self.event_queue.QueuedJobs[:]
        queuedJobs.append(event.job)
        originalRequestSize = event.job.num_required_processors
        waitPredictions = {}
        responsePredictions = {}
	waittime_list = []
	

        if EnabledRunPred:
            self.runTimePredictor.notify_arrival_event(event.job, queuedJobs, self.event_queue.RunningJobs) 
	    
                
            #if self.currentSubmitCount > self.historySetSize:     #in true means no waiting required? but why?
               
                #processor_list,estimated_runtims,histjobs,wt_jobs,ru_jobs,jnu,subtm,prore,usid,rtime,wtime,reqt,qid,my_id,myest,mypoinval,myranpro = self.runTimePredictor.get_prediction(event.job)#CALL FOR RUNTIME PREDICTION job molding
                #print "hello",''
            
	        
            if EnabledWaitPred:
              self.waitTimePredictor.notify_arrival_event(event.job, queuedJobs, self.event_queue.RunningJobs) 
              """
              if self.currentSubmitCount > self.historySetSize:
	       
               if( len(processor_list) > 1):  #processor_list: is the list of required processors for jobs by same user which are in history jobs list. For more explaination refer '__processor_lists' in RuntimePrediction.py
               
                for val in processor_list:
                    self.change_job_attributes(event,val,myest)
                    
                  
                    waitPredictions[val] = self.waitTimePredictor.get_prediction(event.job)		# Getting the wait time prediction lists for different processor
                       
                    
                    waittime_list.append(waitPredictions[val])
               
              
                final_proc = Mainval.Pick_value(processor_list,waittime_list,estimated_runtims) #best processor selection based on gain value
                bestRequestSize = final_proc
                #estimated time calculations
                actual_runtime, actual_ert = assumpt.ert_runtime_list_generator(final_proc,histjobs,wt_jobs,ru_jobs,jnu,subtm,prore,usid,rtime,wtime,reqt,qid,my_id)

                print "Job no:",event.job.id,
		print " Actual Wait time:",event.job.actual_wait_time,
                #print "Runtime_rangeset:",myranpro[0],'\n'
                print " Predicted Wait time:",waittime_list[0],' '
                #print "Runtime_pointval:",mypoinval[0],'\n'
                #print "Job Molding:",'\n'
                #print "requested_processor:",processor_list[0],'\n'
                #print "Processor_Selected:",final_proc,'\n'
                #print "Estimated_runtime:",actual_ert,'\n'
                runningJobIDs = [j.id for j in self.event_queue.RunningJobs]
                allrunningjobevents = self.event_queue.RunningJobs
                #call for delayed submission
                id_list,jobcrid,changid,index_val,delay_list = self.decision_metrics(event,queuedJobs,runningJobIDs,allrunningjobevents,mypoinval[0])
            
		
                #if(jobcrid == changid):
                #
                #  print "Delayed Submission:",'\n'
                #  print "Delay:",0,'\n'
                #  print "Submit_time:",event.job.submit_time,'\n'
		#
                #else:
                #
                # print "Delayed Submission:",'\n'
                # print "Delay:",min(delay_list),'\n'
                # sub = event.job.submit_time + min(delay_list)
                # print "Submit_time:",sub,'\n'
                
		self.modify_job_attributes(event, bestRequestSize, actual_runtime, actual_ert)
                self.waitTimePredictor.notify_arrival_event(event.job, queuedJobs, self.event_queue.RunningJobs)
                self.runTimePredictor.notify_arrival_event(event.job, queuedJobs, self.event_queue.RunningJobs)
	       
	       waitPred = self.waitTimePredictor.get_prediction(event.job)
	       print "Job no:",event.job.id,
	       print "\t",event.job.actual_wait_time,
	       print "\t",waitPred,' '
	      """
        self.queueSimulator.handle_submission_event(event)

    def handle_termination_event(self, event):
        assert isinstance(event, JobTerminationEvent)
        #print 'Term event:', event
        #self.scheduler.cpu_snapshot.printCpuSlices()
        self.queueSimulator.handle_termination_event(event)
        #queuedJobIDs = [j.id for j in self.event_queue.QueuedJobs]
        #runningJobIDs = [j.id for j in self.event_queue.RunningJobs]

        if EnabledWaitPred:
            self.waitTimePredictor.notify_job_termination_event(event.job, self.event_queue.QueuedJobs, self.event_queue.RunningJobs)
	if EnabledRunPred:
            self.runTimePredictor.notify_job_termination_event(event.job)

    def handle_prediction_event(self, event):
        assert isinstance(event, JobPredictionIsOverEvent)
        self.queueSimulator.handle_prediction_event(event)
      
    def run(self, num_processors):
        while not self.event_queue.is_empty:
        #    print_simulator_stats(self.queueSimulator)
            self.event_queue.advance()
        self.do_pred = 1
	#time.sleep(5)
        loop = 1
	while loop == 1:
	    fetch_daily_logs()
            daily_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/prediction/prediction_time/src/daily_log_update/tyrone_daily.swf'	
	    #daily_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/sample_logs/log_daily'
	    daily_file = open(daily_file)
	    if daily_file.closed:
	      print "File status: daily file is closed"
	    else:
	      print "File status: daily file is open"
	    today_jobs = _job_inputs_to_jobs(parse_lines(daily_file), num_processors)

	    runQueuedJobIDs = [j.id for j in self.event_queue.QueuedJobs]
	    runRunningJobIDs = [j.id for j in self.event_queue.RunningJobs]

	    #print "runQueuedJobIDs = ", runQueuedJobIDs
	    #print "runRunningJobIDs = ", runRunningJobIDs
	    #print "self machine jobs=", self.machine.jobs

	    today_count = 0
	    for today_job in today_jobs:
	      if today_job.actual_run_time != 0:
		today_job.start_to_run_at_time = today_job.submit_time + today_job.actual_wait_time
	      if today_job.id in runQueuedJobIDs:
	        self.event_queue.add_event( JobStartEvent(today_job.submit_time + today_job.actual_wait_time, today_job) )   #since job is already queued, hence can be in daily log file only because it started running
	        #add job start event
	      #elif today_job in self.event_queue.RunningJobs:
	      elif today_job.id in runRunningJobIDs:
	        self.event_queue.add_event( JobTerminationEvent(today_job.submit_time + today_job.actual_wait_time + today_job.actual_run_time, today_job) )
	        #add job termination event
	      else:
	        self.event_queue.add_event( JobSubmissionEvent(today_job.submit_time, today_job) )
	    while not self.event_queue.is_empty:	#changing state as these jobs are also considered
	        self.event_queue.advance()
		#print_simulator_stats(self.queueSimulator)
	    time.sleep(86400)
	#time.sleep(1000)
         

    def handle_pred_request(self):		#sid
      loop = 1
      while loop == 1:
        #while(self.do_pred == 0):	#DO-IT when new prediction is requested set this to 1
	#  time.sleep(1)
        req_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/prediction/prediction_time/files/req_file'
	#req_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/sample_logs/log_req'
        try:
	    req_file = open(req_file)
	    #req_file.readline()
	    req_job = _job_input_to_job(JobInput(req_file.readline()), 800)
        finally:
	    if req_file is not sys.stdin:
                req_file.close()

	read_real_logs()
	temp_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/prediction/prediction_time/src/real_time_log_collection/real_time_log_2.swf'
	#temp_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/sample_logs/log_real'
	temp_file = open(temp_file)
	#Imp note: temp_jobs is a generator. Hence normal list funtions like len() won't work
	temp_jobs = _job_inputs_to_jobs(parse_lines(temp_file), 800) #pass no of processors as argument
	
	self.temp_currentSubmitCount = self.currentSubmitCount  #updated at handleSubmissionEvent
	#temp_countSubmissions = self.countSubmissions	
	
	#temp variable deepcopied of original variables
	
	self.temp_scheduler = deepcopy(self.scheduler)

	self.temp_event_queue = EventQueue()
	self.temp_event_queue.events_heap = deepcopy(self.event_queue._events_heap)
	#temp_event_queue._handlers = deepcopy(self.event_queue._handlers) this is giving error. Hence can't copy whole event_queue at once
	self.temp_event_queue._latest_handled_timestamp = deepcopy(self.event_queue._latest_handled_timestamp)
	self.temp_event_queue.RunningJobs = deepcopy(self.event_queue.RunningJobs)
	self.temp_event_queue.QueuedJobs = deepcopy(self.event_queue.QueuedJobs)
	self.temp_event_queue.add_handler(JobSubmissionEvent, self.temp_handle_submission_event)
	self.temp_event_queue.add_handler(JobTerminationEvent, self.temp_handle_termination_event)
	
	self.temp_waitTimePredictor = deepcopy(self.waitTimePredictor)
	self.temp_runTimePredictor = deepcopy(self.runTimePredictor)
	
	self.temp_machine = ValidatingMachine(800, event_queue=self.temp_event_queue, wait_predictor=self.temp_waitTimePredictor, run_predictor = self.temp_runTimePredictor, scheduler = self.temp_scheduler)
	self.temp_machine.jobs = self.machine.jobs
	

	self.temp_queueSimulator = Simulator(self.jobs, 800, self.temp_scheduler, self.temp_event_queue, self.temp_machine, )
	self.temp_queueSimulator.terminated_jobs = self.queueSimulator.terminated_jobs
	self.temp_queueSimulator.time_of_last_job_submission = self.queueSimulator.time_of_last_job_submission

	#remove finished waiting and running jobs from temp_event_queue. As We don't know finish time of jobs waiting or running at day begining but finished now, we need to drop them

	#because job list is generator and for other problems we have to remove jobs through below arduous method

	remove_jobs_id = []
	remove_jobs = []

	queuedJobID = [j.id for j in self.event_queue.QueuedJobs]
	runningJobID = [j.id for j in self.event_queue.RunningJobs]


	temp_jobs_list = []
	temp_jobs_id = []
	temp_shift_jobs = [] #jobs which move from queued to running
	temp_shift_jobs_id = []
	dont_remove_ids = []
	#print "Validation: queuedJobID=", queuedJobID, " runningJobID=", runningJobID
	#print "Validation: Imp: temp_jobs=", len(temp_jobs)
	for job in temp_jobs:
	    print "Validation: real_job_id=", job.id, " actual_run_time=", job.actual_run_time
	    if (job.id in queuedJobID and job.actual_run_time == 0) or (job.id in runningJobID and job.actual_run_time == -1):	#if job is still in same queue, no action
		dont_remove_ids.append(job.id)
	    else:
		if job.id in queuedJobID and job.actual_run_time == -1:	#remove from queued, if moved to running
		    temp_shift_jobs.append(job)
		    temp_shift_jobs_id.append(job.id)
		else:
	    	    temp_jobs_list.append(job)	#list of jobs to be added; either to waiting or running queue
	    	    temp_jobs_id.append(job.id)
	

	print "temp_shift_jobs:",temp_shift_jobs
	print "temp_jobs:",temp_jobs_id
	print "QueuedJobs:",self.event_queue.QueuedJobs
	print "RunningJObs:",self.event_queue.RunningJobs

	for job in self.event_queue.QueuedJobs:	#queued jobs which have been finished
	    if job.id not in temp_jobs_id and job.id not in temp_shift_jobs_id and job.id not in dont_remove_ids:		
		remove_jobs_id.append(job.id)
		
	for job in self.event_queue.RunningJobs:	#running jobs which have been finished
	    if job.id not in temp_jobs_id and job.id not in dont_remove_ids:
		remove_jobs_id.append(job.id)

	for job in self.temp_event_queue.QueuedJobs:
	    if job.id in remove_jobs_id:
		remove_jobs.append(job)

	for job in self.temp_event_queue.RunningJobs:
	    if job.id in remove_jobs_id:
		remove_jobs.append(job)
	    
	for job in remove_jobs:
	    if job in self.temp_event_queue.QueuedJobs:
		print "removed Job from Queued Jobs", job.id,"\n"
	        self.temp_event_queue.QueuedJobs.remove(job)
	    else:
		print "removed Job from Running Jobs", job.id,"\n"
		self.temp_event_queue.RunningJobs.remove(job)
	
	for job in temp_jobs_list:
	    #Validation
	    if job.id == 10499:
		print "Validation: 10499: job.actual_run_time=", job.actual_run_time
	    self.temp_event_queue.add_event(JobSubmissionEvent(job.submit_time,job))

	for job in temp_shift_jobs:
	    self.temp_event_queue.add_event(JobStartEvent(job.submit_time+job.actual_wait_time, job))
	
	while not self.temp_event_queue.is_empty:
	    print_simulator_stats(self.temp_queueSimulator)
	    self.temp_event_queue.advance()
	
	"""
	#Waittime prediction without considering realtime update
        self.runTimePredictor.notify_arrival_event(req_job, self.event_queue.QueuedJobs[:], self.event_queue.RunningJobs)
        self.waitTimePredictor.notify_arrival_event(req_job, self.event_queue.QueuedJobs[:], self.event_queue.RunningJobs)
        waitPred = self.waitTimePredictor.get_prediction(req_job)
	"""

	#Waittime prediction considering realtime update
	pred_queuedJobs = self.temp_event_queue.QueuedJobs[:] #For Deployment
	pred_queuedJobs.append(req_job)		#For Deployment
	self.temp_runTimePredictor.notify_arrival_event(req_job, pred_queuedJobs, self.temp_event_queue.RunningJobs)
        self.temp_waitTimePredictor.notify_arrival_event(req_job, pred_queuedJobs, self.temp_event_queue.RunningJobs)
	print "\nQueued Jobs: ", self.temp_event_queue.QueuedJobs
	print "\nRunning Jobs: ", self.temp_event_queue.RunningJobs
        waitPred = int(self.temp_waitTimePredictor.get_prediction(req_job))
	print "Validation: Prediction=", waitPred

	out_file = '/home/siddharthsahu/Documents/scheduling/scheduling-virtualenv/prediction/prediction_time/files/predictions.txt'
	out_file = open(out_file, 'w')
        out_file.write(str(req_job.id))
        out_file.write("\t")
        out_file.write(str(req_job.actual_wait_time))
        out_file.write("\t")
	out_file.write(str(waitPred))
	out_file.close()
	self.do_pred = 0
        #print "Job no:",req_job.id,
        #print "\t",req_job.actual_wait_time,
        #print "\t",waitPred,
	#print "\t",req_job.user_estimated_run_time,
	#print "\t",req_job.actual_run_time,' '
	loop = loop + 1
    
    def temp_handle_submission_event(self, event):
	    assert isinstance(event, JobSubmissionEvent)
            self.temp_currentSubmitCount += 1
            queuedJobs = self.temp_event_queue.QueuedJobs[:]
            queuedJobs.append(event.job)
            originalRequestSize = event.job.num_required_processors
            waitPredictions = {}
            responsePredictions = {}
	    waittime_list = []
	

            if EnabledRunPred:
                self.temp_runTimePredictor.notify_arrival_event(event.job, queuedJobs, self.temp_event_queue.RunningJobs)     
                if EnabledWaitPred:
                  self.temp_waitTimePredictor.notify_arrival_event(event.job, queuedJobs, self.temp_event_queue.RunningJobs) 
            self.temp_queueSimulator.handle_submission_event(event)


    def temp_handle_termination_event(self, event):
	    assert isinstance(event, JobTerminationEvent)
            self.temp_queueSimulator.handle_termination_event(event)
            #queuedJobIDs = [j.id for j in self.event_queue.QueuedJobs]
            #runningJobIDs = [j.id for j in self.event_queue.RunningJobs]

            if EnabledWaitPred:
                self.temp_waitTimePredictor.notify_job_termination_event(event.job, self.temp_event_queue.QueuedJobs, self.temp_event_queue.RunningJobs)
	    if EnabledRunPred:
                self.temp_runTimePredictor.notify_job_termination_event(event.job)
class MetaScheduler(object):
    """
    This class is the common interface between the User, Predictor and Site Scheduler
    Tasks:
     - Accept job inputs from user
     - Obtain predictions
     - Submit jobs to scheduler
     - Provide feedback (if necessary) to user and predictor
    """

    def __init__(self, jobs, num_processors, scheduler):
        
        self.num_processors = num_processors
        self.jobs = jobs
	print "jobs",jobs
        #print len(self.jobs)
        self.terminated_jobs=[]
        self.scheduler = scheduler
        self.time_of_last_job_submission = 0
        self.event_queue = EventQueue()
        #with open('/home/sharath/Desktop/pyss-read-only/src/5K_sample') as f:
         #  a = sum(1 for _ in f)
        #print "value of history:",a
        self.historySetSize = 100
        self.currentSubmitCount = 0

	if EnabledWaitPred:
            self.waitTimePredictor = WaitPredictor()
	else:
            self.waitTimePredictor = None

        if EnabledRunPred:
            self.runTimePredictor = RunPredictor()
	    
        else:
            self.runTimePredictor = None

        self.machine = ValidatingMachine(num_processors=num_processors, event_queue=self.event_queue, wait_predictor=self.waitTimePredictor, run_predictor = self.runTimePredictor, scheduler = self.scheduler)

        self.event_queue.add_handler(JobSubmissionEvent, self.handle_submission_event)
        self.event_queue.add_handler(JobTerminationEvent, self.handle_termination_event)
        
        if isinstance(scheduler, EasyPlusPlusScheduler) or isinstance(scheduler, ShrinkingEasyScheduler):
            self.event_queue.add_handler(JobPredictionIsOverEvent, self.handle_prediction_event)
        
        countSubmissions = 0    
        for job in self.jobs:
            countSubmissions += 1
            self.event_queue.add_event( JobSubmissionEvent(job.submit_time, job) )     
        #print '** Added', countSubmissions, 'job submission events to event queue **'
        self.queueSimulator = Simulator(jobs, num_processors, scheduler, self.event_queue, self.machine, )

    def modify_job_attributes(self, event, newRequestSize, actual_runtime, actual_ert):
	
	    oldRunTime = event.job.actual_run_time
	    event.job.num_required_processors = newRequestSize
	    event.job.user_estimated_run_time = actual_ert
	    event.job.predicted_run_time = actual_ert
	    if actual_runtime == 0:
		event.job.actual_run_time = actual_ert
	    else:
                event.job.actual_run_time = actual_runtime
           

    def change_job_attributes(self, event, newRequestSize,actual_ert):
            oldRunTime = event.job.actual_run_time
	    event.job.num_required_processors = newRequestSize
	    #event.job.user_estimated_run_time = actual_ert
	    #event.job.predicted_run_time = actual_ert
	    

    def decision_metrics(self, event,queuedJobs,runningJobIDs,allrunningjobevents,jobtarrun):
        
        #print "event:",event
	
       
        #queuedJobIDs = [j.id for j in self.event_queue.QueuedJobs]
        #runningJobIDs = [j.id for j in self.event_queue.RunningJobs]
        #queuedJobIDs.append(event.job.id)
       
        originalRequestSize = event.job.num_required_processors
        waitPredictions = {}
        responsePredictions = {}
	waittime_list = []
        run_list = []
        wait_list = []
        submittime = []
        #terminateval = []
	ifcounter = 0
        if EnabledRunPred:
            run_list.append(jobtarrun)
            submittime.append(event.job.submit_time)
            waitPredictions = self.waitTimePredictor.get_prediction(event.job)
            wait_list.append(waitPredictions)
            pred_run,runid = self.runTimePredictor.get_predictiondelay(event.job)
            
            
            if(len(runid) > 1):
             
             for i in runid:
              ifcounter += 1
              
              for obj in allrunningjobevents:
             	 if obj.id == i in runningJobIDs:
                       terminateval = obj
              
              runningJobIDs.remove(i)
            
              relevantRunningObjs = []
              
	      for obj in allrunningjobevents:
             	 if obj.id in runningJobIDs:
	             relevantRunningObjs.append(obj)
             
              self.runTimePredictor.notify_job_termination_event(terminateval)
              
               
              if EnabledWaitPred:
                    
                    self.waitTimePredictor.notify_arrival_event(event.job, queuedJobs, relevantRunningObjs) 
                    self.runTimePredictor.notify_arrival_event(event.job, queuedJobs, relevantRunningObjs)
                    #if self.currentSubmitCount > self.historySetSize:
                    #print "afterifcondition:"
                    #print "counter:",ifcounter
                    waitPredictions = self.waitTimePredictor.get_prediction(event.job)#to obtain waittime prediction for all running jobs
                    wait_list.append(waitPredictions)
                    #print "wait_prediction:",waitPredictions
                    RunPredictions  = self.runTimePredictor.get_actprediction(event.job)#to obtain runtime prediction for all running jobs
                    #print "run_prediction:",RunPredictions
                    run_list.append(RunPredictions)
                    submittime.append(event.job.submit_time+RunPredictions)
                 
                    runningJobIDs.append(i)
                
             delay = [];decision_list = []
             if( len(wait_list) != [] and len(wait_list) != []):
              l = submittime[0]
              for ru in range(len(run_list)):
                delay.append(abs(l-submittime[ru]))
              
              for k in range(len(wait_list)):
                decision_list.append(wait_list[k]+run_list[k]+delay[k])
              #print "eventjob:",event.job.id
              cjob = event.job.id
              runid.insert(0,cjob)
              inmade = decision_list.index(min(decision_list))
              '''
              print "delay_list:",delay
              print "decision_list:",decision_list,inmade,runid
              print "current_job_id:",cjob
              print "final_jobidsubmission_id:",runid[inmade]
              '''
              return runid,cjob,runid[inmade],inmade,delay
             else:
              empty = []
              return empty,event.job.id,event.job.id,1,empty
            else:
              empty = []
              return empty,event.job.id,event.job.id,1,empty
#study from here

    def handle_submission_event(self, event):
	#print "event",event
        assert isinstance(event, JobSubmissionEvent)
	#print "eventnew",event 
        self.currentSubmitCount += 1
        queuedJobs = self.event_queue.QueuedJobs[:]
        queuedJobs.append(event.job)
	#print "event.job.num_required_processors",event.job.num_required_processors
        originalRequestSize = event.job.num_required_processors
	#print "event.job.actual",event.job.actual_run_time
        waitPredictions = {}
        responsePredictions = {}
	waittime_list = []
	

        if EnabledRunPred:
            #print "parent_jobs:",event.job
            self.runTimePredictor.notify_arrival_event(event.job, queuedJobs, self.event_queue.RunningJobs) 
            self.waitTimePredictor.notify_arrival_event(event.job, queuedJobs, self.event_queue.RunningJobs)          
        self.queueSimulator.handle_submission_event(event)
        
        
    def handle_termination_event(self, event):
        assert isinstance(event, JobTerminationEvent)
        #print 'Term event:', event
        #self.scheduler.cpu_snapshot.printCpuSlices()
        self.queueSimulator.handle_termination_event(event)
        #queuedJobIDs = [j.id for j in self.event_queue.QueuedJobs]
        #runningJobIDs = [j.id for j in self.event_queue.RunningJobs]

        if EnabledWaitPred:
            self.waitTimePredictor.notify_job_termination_event(event.job, self.event_queue.QueuedJobs, self.event_queue.RunningJobs)
	if EnabledRunPred:
            self.runTimePredictor.notify_job_termination_event(event.job)

    def handle_prediction_event(self, event):
        assert isinstance(event, JobPredictionIsOverEvent)
        self.queueSimulator.handle_prediction_event(event)
      
    def run(self):
        while not self.event_queue.is_empty:
            print_simulator_stats(self.queueSimulator)
            self.event_queue.advance()