diff --git a/trunk/manual/00_intro.tex b/trunk/manual/00_intro.tex deleted file mode 100644 index ab096cb..0000000 --- a/trunk/manual/00_intro.tex +++ /dev/null @@ -1,2 +0,0 @@ -\chapter*{Введение} - diff --git a/trunk/manual/40_for_adv.tex b/trunk/manual/for_adv.tex similarity index 100% rename from trunk/manual/40_for_adv.tex rename to trunk/manual/for_adv.tex diff --git a/trunk/manual/30_for_prog.tex b/trunk/manual/for_prog.tex similarity index 96% rename from trunk/manual/30_for_prog.tex rename to trunk/manual/for_prog.tex index 576c5f2..c363556 100644 --- a/trunk/manual/30_for_prog.tex +++ b/trunk/manual/for_prog.tex @@ -261,36 +261,7 @@ default ‘foobar’” Беря во внимание все вышеизложенное, такой результат может вернуть приложение-задача серверу на запрос информации (reltask -i): -%{ -% "title": "Example task", -% "models": [ -% { -% "title": "Example model", -% "data": { -% "energy_max": "int choice [100] default 100 // Максимальная энергия", -% "energy_start": "int default 50 // Начальная энергия", -% "temp_start": "int default -15 // Температура в доме в момент приезда", -% "quota": "int default 200 // Количество работы для выполнения", -% } -% "methods": [ -% { -% "title": "default", -% "data": { -% “temp_hour”: “int default -2 // Изменение температуры в час” -% } -% “results”: -% { -% “data”: { “period”: “period”, “food”: “int” }, -%“table”: -%{ -%“head”: [“time title ‘Time’”, “int title ‘Energy’”, “int title ‘Temperature’”] -%} -% } -%} -% ] -% } -% ] -%} + Описание задачи состоит из списка моделей, которые включают в себя описание полей данных и методов. Методы тоже, как и модели, могут (и должны) включать в себя описание данных, которые будут использоваться управлением алгоритма. diff --git a/trunk/manual/20_for_user.tex b/trunk/manual/for_user.tex similarity index 100% rename from trunk/manual/20_for_user.tex rename to trunk/manual/for_user.tex diff --git a/trunk/manual/intro.tex b/trunk/manual/intro.tex new file mode 100644 index 0000000..f582621 --- /dev/null +++ b/trunk/manual/intro.tex @@ -0,0 +1,3 @@ +\chapter*{Введение} + +О проникновении в нашу жизнь облачных технологий и возврату к терминальному режиму на современном уровне. \ No newline at end of file diff --git a/trunk/manual/listings/answer.json b/trunk/manual/listings/answer.json new file mode 100644 index 0000000..5c2e24b --- /dev/null +++ b/trunk/manual/listings/answer.json @@ -0,0 +1,4 @@ +{ + "title": "test", + "author": "Anton Vakhrushev" +} \ No newline at end of file diff --git a/trunk/manual/opal.tex b/trunk/manual/opal.tex index 1bbb49c..08560f9 100644 --- a/trunk/manual/opal.tex +++ b/trunk/manual/opal.tex @@ -4,9 +4,10 @@ \begin{document} -\include{00_intro} -\include{10_overview} -\include{20_for_user} -\include{30_for_prog} +\include{intro} +\include{overview} +\include{for_user} +\include{for_prog} +\include{outro} \end{document} \ No newline at end of file diff --git a/trunk/manual/outro.tex b/trunk/manual/outro.tex new file mode 100644 index 0000000..826a839 --- /dev/null +++ b/trunk/manual/outro.tex @@ -0,0 +1,3 @@ +\chapter*{Заключение} + +Спасибо за внимание! \ No newline at end of file diff --git a/trunk/manual/10_overview.tex b/trunk/manual/overview.tex similarity index 97% rename from trunk/manual/10_overview.tex rename to trunk/manual/overview.tex index f757e72..1886827 100644 --- a/trunk/manual/10_overview.tex +++ b/trunk/manual/overview.tex @@ -2,7 +2,7 @@ \section{Задача оптимального управления} -В окружающем мире большинство процессов протекают непрерывно с течением времени. Вода не льется из под крана маленькими кубиками, она течет постоянной непрерывной струей, машина не едет "рывками", она плавно едет по извилистой змейке дороги. +В окружающем мире большинство процессов протекают непрерывно с течением времени. Вода не льется из под крана маленькими кубиками, она течет постоянной непрерывной струей, машина не едет <<рывками>>, она плавно едет по извилистой змейке дороги. Но, тем не менее, почти все непрерывные процессы мы можем представить в качестве дискретных. Струю воды можно считать по каплям, а путь автомобиля по пройденным сантиметрам. Такой подход несколько неудобен для человека, который привык к плавности движений и форм. Однако, для вычислительных машин нет ничего лучше! Компьютеры все меряют отдельными значениями. Но если маленьких отдельных значений очень много, то они становятся похожи на непрерывный набор данных, поэтому, в сущности, какая в конечном счете разница что использовать: непрерывные функции или их дискретные аналоги? diff --git a/trunk/server.py b/trunk/server.py index 2221202..5cd551b 100644 --- a/trunk/server.py +++ b/trunk/server.py @@ -21,6 +21,15 @@ import subprocess import task +globallock = threading.Lock() +def WriteToLog(msg): + with globallock: + tm = str(datetime.datetime.now()) + msg = tm + ' ' + str(msg) + #self.log.write(msg + '\n') + print msg + + def GenerateId(data): import hashlib title = data['title'] @@ -35,16 +44,19 @@ class LocalServer: self.max_workers = 2 self.task_descrs = [] - self.task_queue = [] + self.jobs_queue = [] self.log = None - self.lock = threading.Lock() + self.queue_lock = threading.Lock() # init actions self.log = open('log.txt', 'w') self.WriteToLog('local server initialized') + worker = Worker(self.jobs_queue, self.queue_lock) + worker.start() + def Close(self): self.WriteToLog('local server closed\n') @@ -76,8 +88,10 @@ class LocalServer: try: # нормализуем указанный путь line = os.path.normpath(line) + line = os.path.abspath(line) # считываем данные через shell (важно для скриптовых языков) - textdata = subprocess.check_output([line, '-i'], shell = True) + textdata = subprocess.check_output([line, '-i'], shell = True, + cwd = os.path.dirname(line)) # загружаем данные описания задачи data = json.loads(textdata) # провряем их на корректность @@ -106,8 +120,11 @@ class LocalServer: def GetJob(self, index): pass - def AddJob(self, taskdescr, data): - pass + def AddJob(self, taskd, datadump): + job = Job(taskd, datadump) + with self.queue_lock: + self.jobs_queue.append(job) + WriteToLog('Job added') #------------------------------------------------------------------------------- @@ -117,19 +134,22 @@ class Worker(threading.Thread): self.queue = queue self.lock = lock self.daemon = True + WriteToLog('worker started') def FindNext(self): result = None for job in self.queue: - if job.GetStatus() == JOB_STOP: + if job.GetState() == JOB_READY: result = job return result def run(self): while True: job = None + # найти следующее готовое к выполнению задание with self.lock: - job = FindNext() + job = self.FindNext() + # и, если нашли, приступаем к выполнению if job: job.Start() else: @@ -137,32 +157,57 @@ class Worker(threading.Thread): #------------------------------------------------------------------------------- -JOB_STOP = 0 -JOB_RUN = 1 -JOB_PAUSE = 2 -JOB_COMPLETE = 4 +JOB_READY = 0 +JOB_RUNNING = 1 +JOB_STOPPED = 2 +JOB_COMPLETED = 3 class Job: def __init__(self, taskd, datadump): self.taskd = taskd self.datad = datadump - self.status = JOB_STOP + self.state = JOB_READY self.percent = 0.0 self.result = None + self.proc = None - #self. + def ProcessMsg(self, msg): + WriteToLog(msg.strip()) def Start(self): - pass + #try: + self.state = JOB_RUNNING + WriteToLog('Job started') + execpath = self.taskd.execpath + # запускаем процесс на выполнение + self.proc = subprocess.Popen([execpath, '-r'], shell = True, + stdin = subprocess.PIPE, stdout = subprocess.PIPE, + stderr = subprocess.STDOUT, cwd = os.path.dirname(execpath)) + # передаем стартовые параметры + istream = self.proc.stdin + ostream = self.proc.stdout + istream.write(self.datad + '\n') + istream.flush() + # пока процесс не завершится (или его не прибьют) + while self.proc.poll() == None: + try: + msg = ostream.readline() + self.ProcessMsg(msg) + except Exception, e: + WriteToLog('Income msg failed' + str(e)) + self.state = JOB_COMPLETED + WriteToLog('Job done') + #except: + #WriteToLog('Job loop failed') + #self.state = JOB_STOPPED def Stop(self): - pass + if self.proc and self.proc.poll() != None: + self.proc.kill() + WriteToLog('Job killed') - def Pause(self): - pass - - def GetStatus(self): - return self.status + def GetState(self): + return self.state def IsComplete(self): return self.GetStatus() == JOB_COMPLETE diff --git a/trunk/task.py b/trunk/task.py index a28aac4..a6b2dc6 100644 --- a/trunk/task.py +++ b/trunk/task.py @@ -29,7 +29,7 @@ class TaskDescription: self.data = data self.models = [] for label, data in self.data['models'].iteritems(): - self.models.append(DataDescription(self, label, data, self.server)) + self.models.append(DataDescription(None, label, data, self)) def GetModelsDescriptions(self): return self.models @@ -126,20 +126,23 @@ class DataDefinition: raise ValueError def PackParams(self): - - owner = self package = [] + owner = self while owner: data = {'label': owner.DD.GetLabel(), 'params': owner.params} package.append(data) owner = owner.parent package.reverse() + return json.dumps(package) - return package + def Flush(self): + server = self.DD.taskd.server + datadump = self.PackParams() + server.AddJob(self.DD.taskd, datadump) #------------------------------------------------------------------------------- -import server, json +import server, json, time from pprint import pprint def main(): @@ -153,11 +156,15 @@ def main(): model = models[0] mdef = DataDefinition(model) - #pprint(mdef.DD.data) + pprint(mdef.DD.data) mdef['x'] = 20 p = mdef.PackParams() pprint(p) + mdef.Flush() + mdef.Flush() + + time.sleep(15) if __name__ == '__main__': main() diff --git a/trunk/tasks/testt.js b/trunk/tasks/testt.json similarity index 100% rename from trunk/tasks/testt.js rename to trunk/tasks/testt.json diff --git a/trunk/tasks/testt.py b/trunk/tasks/testt.py index f787eeb..cfc7e33 100644 --- a/trunk/tasks/testt.py +++ b/trunk/tasks/testt.py @@ -3,22 +3,27 @@ import sys import json import os +import time + +def write(msg): + sys.stdout.write(msg + '\n') + sys.stdout.flush() def main(): # try: - d = os.path.dirname(__file__) - os.chdir(d) - if sys.argv[1] == '-i': - with open('testt.js') as f: + with open('testt.json') as f: d = json.load(f) - print json.dumps(d, indent = 2) + write(json.dumps(d, indent = 2)) elif sys.argv[1] == '-r': textdata = raw_input() - data = json.loads(data) + #data = json.loads(data) + for i in xrange(10): + time.sleep(0.5) + write(json.dumps({ "hello": "world" })) # except: # print 'Error!'