Ignore:
Timestamp:
Jan 11, 2012, 3:13:30 PM (12 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
d21198f
Parents:
be6ff03
git-author:
Jessica B. Hamrick <jhamrick@…> (01/11/12 15:13:30)
git-committer:
Jessica B. Hamrick <jhamrick@…> (01/11/12 15:13:30)
Message:

Better threading model

File:
1 edited

Legend:

Unmodified
Added
Removed
  • server/lib/gutenbach/server/printer.py

    rb01b6d1 reee389a  
    1 from . import InvalidJobException, InvalidPrinterStateException
     1from . import InvalidJobException, InvalidPrinterStateException, InvalidJobStateException
    22from . import Job
    33from gutenbach.ipp import PrinterStates as States
     
    55import logging
    66import time
     7import threading
     8import heapq
     9import traceback
     10import sys
     11
    712
    813# initialize logger
    914logger = logging.getLogger(__name__)
    1015
    11 class GutenbachPrinter(object):
     16class GutenbachPrinter(threading.Thread):
    1217
    1318    # for IPP
     
    4449    ]
    4550       
    46     def __init__(self, name):
    47 
    48         self.name = name
    49         self.time_created = int(time.time())
    50         self.state = States.IDLE
    51 
    52         self.finished_jobs = []
    53         self.active_jobs = []
    54         self.jobs = {}
    55 
    56         # cups ignores jobs with id 0, so we have to start at 1
    57         self._next_jobid = 1
     51    def __init__(self, name, *args, **kwargs):
     52        self.lock = threading.RLock()
     53
     54        with self.lock:
     55            super(GutenbachPrinter, self).__init__(*args, **kwargs)
     56           
     57            self.name = name
     58            self.time_created = int(time.time())
     59
     60            self.finished_jobs = []
     61            self.pending_jobs = []
     62            self.current_job = None
     63            self.jobs = {}
     64
     65            self.running = False
     66            self.paused = False
     67
     68            # CUPS ignores jobs with id 0, so we have to start at 1
     69            self._next_job_id = 1
    5870
    5971    def __repr__(self):
     
    7890
    7991    @property
    80     def next_job(self):
    81         if len(self.active_jobs) == 0:
    82             job = None
    83         else:
    84             job = self.active_jobs[0]
     92    def state(self):
     93        with self.lock:
     94            if self.current_job is not None:
     95                val = States.PROCESSING
     96            elif len(self.pending_jobs) == 0:
     97                val = States.IDLE
     98            else:
     99                val = States.STOPPED
     100        return val
     101
     102    @property
     103    def active_jobs(self):
     104        with self.lock:
     105            jobs = self.pending_jobs[:]
     106            if self.current_job is not None:
     107                jobs.insert(0, self.current_job.id)
     108        return jobs
     109
     110    ######################################################################
     111    ###                            Methods                             ###
     112    ######################################################################
     113
     114    def run(self):
     115        self.running = True
     116        while self.running:
     117            with self.lock:
     118                try:
     119                    if self.current_job is None:
     120                        self.start_job()
     121                    elif self.current_job.is_finished:
     122                        self.complete_job()
     123                except:
     124                    logger.fatal(traceback.format_exc())
     125                    sys.exit(1)
     126            time.sleep(0.1)
     127
     128    def start_job(self):
     129        with self.lock:
     130            if self.current_job is None:
     131                try:
     132                    job_id = heapq.heappop(self.pending_jobs)
     133                    self.current_job = self.get_job(job_id)
     134                    self.current_job.play()
     135                except IndexError:
     136                    pass
     137                except InvalidJobStateException:
     138                    heapq.heappush(self.pending_jobs, self.current_job.id)
     139                finally:
     140                    self.current_job = None
     141                   
     142    def complete_job(self):
     143        with self.lock:
     144            if self.current_job is None:
     145                return
     146
     147            try:
     148                if not self.current_job.is_finished:
     149                    self.current_job.stop()
     150            finally:
     151                self.finished_jobs.append(self.current_job)
     152                self.current_job = None
     153
     154    def stop(self):
     155        pass
     156
     157    def get_job(self, job_id):
     158        with self.lock:
     159            if job_id not in self.jobs:
     160                raise InvalidJobException(job_id)
     161            job = self.jobs[job_id]
    85162        return job
    86 
    87     ######################################################################
    88     ###                            Methods                             ###
    89     ######################################################################
    90 
    91     def complete_job(self, jobid):
    92         job = self.jobs[self.active_jobs.pop(0)]
    93         self.finished_jobs.append(job)
    94         job.finish()
    95         return job.id
    96 
    97     def start_job(self, jobid):
    98         job = self.jobs[self.active_jobs[0]]
    99         if job.status != ipp.JobStates.PENDING:
    100             raise InvalidPrinterStateException(job.status)
    101         job.play()
    102 
    103     def stop(self):
    104         if len(self.active_jobs) == 0:
    105             return
    106         job = self.jobs[self.active_jobs[0]]
    107         if job.player is not None:
    108             logger.info("stopping printer %s" % self.name)
    109             job.player.terminate()
    110 
    111     def get_job(self, jobid):
    112         if jobid not in self.jobs:
    113             raise InvalidJobException(jobid)
    114         return self.jobs[jobid]
    115163
    116164    ######################################################################
     
    238286
    239287    def create_job(self, requesting_user_name="", job_name="", job_k_octets=0):
    240         job_id = self._next_jobid
    241         self._next_jobid += 1
     288        job_id = self._next_job_id
     289        self._next_job_id += 1
    242290       
    243291        job = Job(job_id,
     
    248296       
    249297        self.jobs[job_id] = job
    250         self.active_jobs.append(job_id)
    251         self.state = States.PROCESSING
     298        self.pending_jobs.append(job_id)
    252299       
    253300        return job
Note: See TracChangeset for help on using the changeset viewer.