Ticket #2346: 2346-loops.patch

File 2346-loops.patch, 5.8 KB (added by robertwb, 14 years ago)
  • sage/server/notebook/worksheet.py

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1204919477 28800
    # Node ID 0361af1564fbd612443e3bc8905bcb86105a90d7
    # Parent  fb84b75cb6f418413bc943198fbe49b595c57e72
    Use loopback, fix user-supplied timeout value
    
    diff -r fb84b75cb6f4 -r 0361af1564fb sage/server/notebook/worksheet.py
    a b class Worksheet: 
    12231223        # TODOss
    12241224        os.system('chmod -R a+rw "%s"'%absD)
    12251225       
    1226         print "timing"
    12271226        if C.time():
    12281227            input += '__SAGE_t__=cputime()\n__SAGE_w__=walltime()\n'
    12291228        if I.endswith('?'):
    class Worksheet: 
    12791278            self.restart_sage()
    12801279            C.set_output_text('The Sage compute process quit (possibly Sage crashed?).\nPlease retry your calculation.','')
    12811280               
    1282     def check_comp(self):
     1281    def check_comp(self, wait=0.2):
    12831282        if len(self.__queue) == 0:
    12841283            return 'e', None
    12851284        S = self.sage()
    class Worksheet: 
    12901289            return 'd', C
    12911290
    12921291        try:
    1293             done, out, new = S._so_far(wait=0.2, alternate_prompt=SAGE_END+str(self.synchro()))
     1292            done, out, new = S._so_far(wait=wait, alternate_prompt=SAGE_END+str(self.synchro()))
    12941293        except RuntimeError, msg:
    12951294            verbose("Computation was interrupted or failed. Restarting.\n%s"%msg)
    12961295            self.__comp_is_running = False
  • sage/server/simple/twist.py

    diff -r fb84b75cb6f4 -r 0361af1564fb sage/server/simple/twist.py
    a b r""" 
    11r"""
    22This module provides a very simple API for interacting with a Sage session
    33over http. It runs in as part of the notebook server.
     4
     5NOTE:
     6    The exact data in the JSON header may vary over time (for example, further
     7    data may be added), but should remain backwards compatable if it is being
     8    parsed as JSON data.
     9
    410
    511TESTS:
    612    sage: from sage.server.notebook.notebook_object import test_notebook
    Run a command: 
    3137    4
    3238
    3339Do a longer-running example:
    34     sage: n = next_prime(10^80)*next_prime(10^90)
    35     sage: print get_url('https://localhost:8095/simple/compute?session=%s&code=factor(%s)' % (session, n))
     40    sage: n = next_prime(10^25)*next_prime(10^30)
     41    sage: print get_url('https://localhost:8095/simple/compute?session=%s&code=factor(%s)&timeout=0.1' % (session, n))
    3642    {
    3743    "status": "computing",
    3844    "files": [],
    Log out: 
    8086
    8187import re, random, os.path, shutil, time
    8288
    83 from twisted.internet.threads import deferToThread
     89from twisted.internet.task import LoopingCall
    8490from twisted.python import log
    8591from twisted.internet import defer, reactor
    8692from twisted.cred import credentials
    class RestartResource(resource.Resource) 
    208214
    209215class CellResource(resource.Resource):
    210216
    211     def wait_for_comp(self, cell, timeout):
    212         """
    213         This function polls the worksheet and exits when the computation finishes
    214         or timeout seconds have elapsed.
    215        
    216         It would seem twisted would have a builtin mechanism to do this...
    217         """
    218         t = time.time()
    219         cell.worksheet().check_comp()
    220         if not cell.computing() or timeout <= 0:
    221             return self.render_cell_result(cell)
    222         else:
    223             poll_freq = 0.25
    224             d = defer.Deferred()
    225             d.addCallback(self.wait_for_comp, timeout-poll_freq-(time.time()-t))
    226             reactor.callLater(poll_freq, d.callback, cell)
    227             return d
     217    def start_comp(self, cell, timeout):
     218        start_time = time.time()
     219        looper_list = []
     220        looper = LoopingCall(self.check_comp, cell, start_time, timeout, looper_list)
     221        looper_list.append(looper) # so check_comp has access
     222        looper.cell = cell # to pass it on
     223        d = looper.start(0.25, now=True)
     224        d.addCallback(self.render_cell_result)
     225        return d
     226           
     227    def check_comp(self, cell, start_time, timeout, looper_list):
     228        cell.worksheet().check_comp(wait=0.01) # don't want to block, delay handled by twisted
     229        if not cell.computing() or time.time() - start_time > timeout:
     230            looper_list[0].stop()
    228231
    229     def render_cell_result(self, cell):
     232    def render_cell_result(self, looper):
     233        cell = looper.cell
    230234        if cell.interrupted():
    231235            cell_status = 'interrupted'
    232236        elif cell.computing():
    class ComputeResource(CellResource): 
    246250        except KeyError:
    247251            return http.Response(stream = "Invalid session.")
    248252        try:
    249             timeout = float(sessions[ctx.args['timeout'][0]])
    250         except KeyError, ValueError:
     253            timeout = float(ctx.args['timeout'][0])
     254        except (KeyError, ValueError), msg:
    251255            timeout = session.default_timeout
    252256        cell = session.worksheet.append_new_cell()
    253257        cell.set_input_text(ctx.args['code'][0])
    254258        cell.evaluate(username = session.username)
    255         return self.wait_for_comp(cell, timeout)
     259        return self.start_comp(cell, timeout)
    256260                   
    257261
    258262class StatusResource(CellResource):
    class StatusResource(CellResource): 
    266270            cell_id = int(ctx.args['cell'][0])
    267271            cell = session.worksheet.get_cell_with_id(cell_id)
    268272            try:
    269                 timeout = float(sessions[ctx.args['timeout'][0]])
     273                timeout = float(ctx.args['timeout'][0])
    270274            except KeyError, ValueError:
    271275                timeout = -1
    272             return self.wait_for_comp(cell, timeout)
     276            return self.start_comp(cell, timeout)
    273277        except KeyError:
    274278            status = session.get_status()
    275279            return http.Response(stream = "%s\n%s\n" % (simple_jsonize(status), SEP))