~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/buildmaster/model/builder.py

[r=allenap, bac, gmb, julian-edwards, wallyworld][bug=905853, 905855,
 906079] In buildmaster,
 always shift into a read-write database transaction access mode before
 updating PackageBuild statuses. Shift into read-write transactions in
 appropriate places in TranslationTemplatesBuildBehavior. Ensure that all
 lp.buildmaster tests to which it is relevant are running with
 BuilddManagerTestFixture.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2009,2011 Canonical Ltd.  This software is licensed under the
 
1
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
2
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
3
 
4
4
# pylint: disable-msg=E0611,W0212
66
66
    SQLBase,
67
67
    sqlvalues,
68
68
    )
 
69
from lp.services.database.transaction_policy import DatabaseTransactionPolicy
69
70
from lp.services.helpers import filenameToContentType
70
71
from lp.services.job.interfaces.job import JobStatus
71
72
from lp.services.job.model.job import Job
545
546
 
546
547
    def setSlaveForTesting(self, proxy):
547
548
        """See IBuilder."""
 
549
        # XXX JeroenVermeulen 2011-11-09, bug=888010: Don't use this.
 
550
        # It's a trap.  See bug for details.
548
551
        self._testing_slave = proxy
549
552
        del get_property_cache(self).slave
550
553
 
673
676
                bytes_written = out_file.tell()
674
677
                out_file.seek(0)
675
678
 
676
 
                library_file = getUtility(ILibraryFileAliasSet).create(
677
 
                    filename, bytes_written, out_file,
678
 
                    contentType=filenameToContentType(filename),
679
 
                    restricted=private)
 
679
                transaction.commit()
 
680
                with DatabaseTransactionPolicy(read_only=False):
 
681
                    library_file = getUtility(ILibraryFileAliasSet).create(
 
682
                        filename, bytes_written, out_file,
 
683
                        contentType=filenameToContentType(filename),
 
684
                        restricted=private)
 
685
                    transaction.commit()
680
686
            finally:
681
687
                # Remove the temporary file.  getFile() closes the file
682
688
                # object.
714
720
    def acquireBuildCandidate(self):
715
721
        """Acquire a build candidate in an atomic fashion.
716
722
 
717
 
        When retrieiving a candidate we need to mark it as building
 
723
        When retrieving a candidate we need to mark it as building
718
724
        immediately so that it is not dispatched by another builder in the
719
725
        build manager.
720
726
 
724
730
        can be in this code at the same time.
725
731
 
726
732
        If there's ever more than one build manager running at once, then
727
 
        this code will need some sort of mutex.
 
733
        this code will need some sort of mutex, or run in a single
 
734
        transaction.
728
735
        """
729
736
        candidate = self._findBuildCandidate()
730
737
        if candidate is not None:
731
 
            candidate.markAsBuilding(self)
732
738
            transaction.commit()
 
739
            with DatabaseTransactionPolicy(read_only=False):
 
740
                candidate.markAsBuilding(self)
 
741
                transaction.commit()
733
742
        return candidate
734
743
 
735
744
    def _findBuildCandidate(self):
792
801
        store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
793
802
        candidate_jobs = store.execute(query).get_all()
794
803
 
795
 
        for (candidate_id,) in candidate_jobs:
796
 
            candidate = getUtility(IBuildQueueSet).get(candidate_id)
797
 
            job_class = job_classes[candidate.job_type]
798
 
            candidate_approved = job_class.postprocessCandidate(
799
 
                candidate, logger)
800
 
            if candidate_approved:
801
 
                return candidate
 
804
        transaction.commit()
 
805
        with DatabaseTransactionPolicy(read_only=False):
 
806
            for (candidate_id,) in candidate_jobs:
 
807
                candidate = getUtility(IBuildQueueSet).get(candidate_id)
 
808
                job_class = job_classes[candidate.job_type]
 
809
                candidate_approved = job_class.postprocessCandidate(
 
810
                    candidate, logger)
 
811
                if candidate_approved:
 
812
                    transaction.commit()
 
813
                    return candidate
 
814
            transaction.commit()
802
815
 
803
816
        return None
804
817