def test_noWorkDoneWhenConcurrentlyDeleted(self):
        """
        When a L{WorkItem} is concurrently deleted by another transaction, it
        should I{not} perform its work.
        """
        # Provide access to a method called 'concurrently' everything using
        original = self.store.newTransaction
        def decorate(*a, **k):
            result = original(*a, **k)
            result.concurrently = self.store.newTransaction
            return result
        self.store.newTransaction = decorate

        def operation(txn):
            return txn.enqueue(DummyWorkItem, a=30, b=40, workID=5678,
                               deleteOnLoad=1,
                               notBefore=datetime.datetime.utcnow())
        proposal = yield inTransaction(self.store.newTransaction, operation)
        yield proposal.whenExecuted()
        # Sanity check on the concurrent deletion.
        def op2(txn):
            return Select([schema.DUMMY_WORK_ITEM.WORK_ID],
                          From=schema.DUMMY_WORK_ITEM).on(txn)
        rows = yield inTransaction(self.store.newTransaction, op2)
        self.assertEquals(rows, [])
        def op3(txn):
            return Select([schema.DUMMY_WORK_DONE.WORK_ID,
                           schema.DUMMY_WORK_DONE.A_PLUS_B],
                          From=schema.DUMMY_WORK_DONE).on(txn)
        rows = yield inTransaction(self.store.newTransaction, op3)
        self.assertEquals(rows, [])
 def deschema():
     @inlineCallbacks
     def deletestuff(txn):
         for stmt in dropSQL:
             yield txn.execSQL(stmt)
     return inTransaction(lambda *a: self.store.newTransaction(*a),
                          deletestuff)
Esempio n. 3
0
        def deschema():
            @inlineCallbacks
            def deletestuff(txn):
                for stmt in dropSQL:
                    yield txn.execSQL(stmt)

            return inTransaction(lambda *a: self.store.newTransaction(*a),
                                 deletestuff)
Esempio n. 4
0
    def test_noWorkDoneWhenConcurrentlyDeleted(self):
        """
        When a L{WorkItem} is concurrently deleted by another transaction, it
        should I{not} perform its work.
        """
        # Provide access to a method called "concurrently" everything using
        original = self.store.newTransaction

        def decorate(*a, **k):
            result = original(*a, **k)
            result.concurrently = self.store.newTransaction
            return result

        self.store.newTransaction = decorate

        def operation(txn):
            return txn.enqueue(DummyWorkItem,
                               a=30,
                               b=40,
                               workID=5678,
                               deleteOnLoad=1,
                               notBefore=datetime.datetime.utcnow())

        proposal = yield inTransaction(self.store.newTransaction, operation)
        yield proposal.whenExecuted()

        # Sanity check on the concurrent deletion.
        def op2(txn):
            return Select([schema.DUMMY_WORK_ITEM.WORK_ID],
                          From=schema.DUMMY_WORK_ITEM).on(txn)

        rows = yield inTransaction(self.store.newTransaction, op2)
        self.assertEquals(list(rows), [])

        def op3(txn):
            return Select([
                schema.DUMMY_WORK_DONE.WORK_ID,
                schema.DUMMY_WORK_DONE.A_PLUS_B,
            ],
                          From=schema.DUMMY_WORK_DONE).on(txn)

        rows = yield inTransaction(self.store.newTransaction, op3)
        self.assertEquals(list(rows), [])
Esempio n. 5
0
 def test_currentNodeInfo(self):
     """
     There will be two C{NODE_INFO} rows in the database, retrievable as two
     L{NodeInfo} objects, once both nodes have started up.
     """
     @inlineCallbacks
     def check(txn):
         self.assertEquals(len((yield self.node1.activeNodes(txn))), 2)
         self.assertEquals(len((yield self.node2.activeNodes(txn))), 2)
     return inTransaction(self.store.newTransaction, check)
Esempio n. 6
0
    def test_currentNodeInfo(self):
        """
        There will be two C{NODE_INFO} rows in the database, retrievable as two
        L{NodeInfo} objects, once both nodes have started up.
        """
        @inlineCallbacks
        def check(txn):
            self.assertEquals(len((yield self.node1.activeNodes(txn))), 2)
            self.assertEquals(len((yield self.node2.activeNodes(txn))), 2)

        return inTransaction(self.store.newTransaction, check)
Esempio n. 7
0
 def test_enqueueHappyPath(self):
     """
     When a L{WorkItem} is scheduled for execution via
     L{PeerConnectionPool.enqueueWork} its C{doWork} method will be invoked
     by the time the L{Deferred} returned from the resulting
     L{WorkProposal}'s C{whenExecuted} method has fired.
     """
     # TODO: this exact test should run against LocalQueuer as well.
     def operation(txn):
         # TODO: how does 'enqueue' get associated with the transaction? This
         # is not the fact with a raw t.w.enterprise transaction.  Should
         # probably do something with components.
         return txn.enqueue(DummyWorkItem, a=3, b=4, workID=4321,
                            notBefore=datetime.datetime.utcnow())
     result = yield inTransaction(self.store.newTransaction, operation)
     # Wait for it to be executed.  Hopefully this does not time out :-\.
     yield result.whenExecuted()
     def op2(txn):
         return Select([schema.DUMMY_WORK_DONE.WORK_ID,
                        schema.DUMMY_WORK_DONE.A_PLUS_B],
                        From=schema.DUMMY_WORK_DONE).on(txn)
     rows = yield inTransaction(self.store.newTransaction, op2)
     self.assertEquals(rows, [[4321, 7]])
    def setUp(self):
        """
        L{PeerConnectionPool} requires access to a database and the reactor.
        """
        self.store = yield buildStore(self, None)
        def doit(txn):
            return txn.execSQL(schemaText)
        yield inTransaction(lambda: self.store.newTransaction("bonus schema"),
                            doit)
        def indirectedTransactionFactory(*a):
            """
            Allow tests to replace 'self.store.newTransaction' to provide
            fixtures with extra methods on a test-by-test basis.
            """
            return self.store.newTransaction(*a)
        def deschema():
            @inlineCallbacks
            def deletestuff(txn):
                for stmt in dropSQL:
                    yield txn.execSQL(stmt)
            return inTransaction(lambda *a: self.store.newTransaction(*a),
                                 deletestuff)
        self.addCleanup(deschema)

        from twisted.internet import reactor
        self.node1 = PeerConnectionPool(
            reactor, indirectedTransactionFactory, 0, schema)
        self.node2 = PeerConnectionPool(
            reactor, indirectedTransactionFactory, 0, schema)

        class FireMeService(Service, object):
            def __init__(self, d):
                super(FireMeService, self).__init__()
                self.d = d
            def startService(self):
                self.d.callback(None)
        d1 = Deferred()
        d2 = Deferred()
        FireMeService(d1).setServiceParent(self.node1)
        FireMeService(d2).setServiceParent(self.node2)
        ms = MultiService()
        self.node1.setServiceParent(ms)
        self.node2.setServiceParent(ms)
        ms.startService()
        self.addCleanup(ms.stopService)
        yield gatherResults([d1, d2])
        self.store.queuer = self.node1
Esempio n. 9
0
    def test_inTransactionSuccess(self):
        """
        L{inTransaction} invokes its C{transactionCreator} argument, and then
        returns a L{Deferred} which fires with the result of its C{operation}
        argument when it succeeds.
        """
        class faketxn(object):
            def __init__(self):
                self.commits = []
                self.aborts = []

            def commit(self):
                self.commits.append(Deferred())
                return self.commits[-1]

            def abort(self):
                self.aborts.append(Deferred())
                return self.aborts[-1]

        createdTxns = []

        def createTxn():
            createdTxns.append(faketxn())
            return createdTxns[-1]

        dfrs = []

        def operation(t):
            self.assertIdentical(t, createdTxns[-1])
            dfrs.append(Deferred())
            return dfrs[-1]

        d = inTransaction(createTxn, operation)
        x = []
        d.addCallback(x.append)
        self.assertEquals(x, [])
        self.assertEquals(len(dfrs), 1)
        dfrs[0].callback(35)

        # Commit in progress, so still no result...
        self.assertEquals(x, [])
        createdTxns[0].commits[0].callback(42)

        # Committed, everything's done.
        self.assertEquals(x, [35])
Esempio n. 10
0
    def test_inTransactionSuccess(self):
        """
        L{inTransaction} invokes its C{transactionCreator} argument, and then
        returns a L{Deferred} which fires with the result of its C{operation}
        argument when it succeeds.
        """
        class faketxn(object):
            def __init__(self):
                self.commits = []
                self.aborts = []
            def commit(self):
                self.commits.append(Deferred())
                return self.commits[-1]
            def abort(self):
                self.aborts.append(Deferred())
                return self.aborts[-1]

        createdTxns = []
        def createTxn():
            createdTxns.append(faketxn())
            return createdTxns[-1]
        dfrs = []
        def operation(t):
            self.assertIdentical(t, createdTxns[-1])
            dfrs.append(Deferred())
            return dfrs[-1]
        d = inTransaction(createTxn, operation)
        x = []
        d.addCallback(x.append)
        self.assertEquals(x, [])
        self.assertEquals(len(dfrs), 1)
        dfrs[0].callback(35)
        # Commit in progress, so still no result...
        self.assertEquals(x, [])
        createdTxns[0].commits[0].callback(42)
        # Committed, everything's done.
        self.assertEquals(x, [35])
Esempio n. 11
0
    def generateSchedulingResponses(self):
        def failForRecipient(recipient):
            err = HTTPError(ErrorResponse(
                responsecode.FORBIDDEN,
                (caldav_namespace, "recipient-failed"),
                "iMIP request failed",
            ))
            self.responses.add(
                recipient.cuaddr,
                Failure(exc_value=err),
                reqstatus=iTIPRequestStatus.SERVICE_UNAVAILABLE,
                suppressErrorLog=True
            )

        # Generate an HTTP client request
        try:
            # We do not do freebusy requests via iMIP
            if self.freebusy:
                raise ValueError("iMIP VFREEBUSY requests not supported.")

            method = self.scheduler.calendar.propertyValue("METHOD")
            if method not in (
                "PUBLISH",
                "REQUEST",
                "REPLY",
                "ADD",
                "CANCEL",
                "DECLINE_COUNTER",
            ):
                log.info("Could not do server-to-imip method: %s" % (method,))
                for recipient in self.recipients:
                    err = HTTPError(ErrorResponse(
                        responsecode.FORBIDDEN,
                        (caldav_namespace, "recipient-failed"),
                        "iMIP method not allowed: %s" % (method,),
                    ))
                    self.responses.add(
                        recipient.cuaddr,
                        Failure(exc_value=err),
                        reqstatus=iTIPRequestStatus.NO_USER_SUPPORT
                    )
                returnValue(None)

            caldata = str(self.scheduler.calendar)

            for recipient in self.recipients:
                try:
                    toAddr = str(recipient.cuaddr)
                    if not toAddr.lower().startswith("mailto:"):
                        raise ValueError("ATTENDEE address '%s' must be mailto: for iMIP operation." % (toAddr,))

                    fromAddr = str(self.scheduler.originator.cuaddr)

                    log.debug("Submitting iMIP message...  To: '%s', From :'%s'\n%s" % (toAddr, fromAddr, caldata,))

                    def enqueueOp(txn):
                        return txn.enqueue(IMIPInvitationWork, fromAddr=fromAddr,
                            toAddr=toAddr, icalendarText=caldata)

                    yield inTransaction(
                        lambda: self.scheduler.txn.store().newTransaction(
                            "Submitting iMIP message for UID: %s" % (
                            self.scheduler.calendar.resourceUID(),)),
                        enqueueOp
                    )

                except Exception, e:
                    # Generated failed response for this recipient
                    log.debug("iMIP request %s failed for recipient %s: %s" % (self, recipient, e))
                    failForRecipient(recipient)

                else:
                    self.responses.add(
                        recipient.cuaddr,
                        responsecode.OK,
                        reqstatus=iTIPRequestStatus.MESSAGE_SENT
                    )

        except Exception, e:
            # Generated failed responses for each recipient
            log.debug("iMIP request %s failed: %s" % (self, e))
            for recipient in self.recipients:
                failForRecipient(recipient)
Esempio n. 12
0
 def thunk(operation):
     return inTransaction(transactionCreator, operation)
Esempio n. 13
0
    def setUp(self):
        """
        L{PeerConnectionPool} requires access to a database and the reactor.
        """
        self.store = yield buildStore(self, None)

        @inlineCallbacks
        def doit(txn):
            for statement in splitSQLString(nodeSchema + schemaText):
                yield txn.execSQL(statement)

        yield inTransaction(lambda: self.store.newTransaction("bonus schema"),
                            doit)

        def indirectedTransactionFactory(*a):
            """
            Allow tests to replace "self.store.newTransaction" to provide
            fixtures with extra methods on a test-by-test basis.
            """
            return self.store.newTransaction(*a)

        def deschema():
            @inlineCallbacks
            def deletestuff(txn):
                for stmt in dropSQL:
                    yield txn.execSQL(stmt)
                txn.execSQL("drop table node_info")

            return inTransaction(lambda *a: self.store.newTransaction(*a),
                                 deletestuff)

        self.addCleanup(deschema)

        from twisted.internet import reactor
        self.node1 = PeerConnectionPool(reactor, indirectedTransactionFactory,
                                        0, schema)
        self.node2 = PeerConnectionPool(reactor, indirectedTransactionFactory,
                                        0, schema)

        class FireMeService(Service, object):
            def __init__(self, d):
                super(FireMeService, self).__init__()
                self.d = d

            def startService(self):
                self.d.callback(None)

        d1 = Deferred()
        d2 = Deferred()
        FireMeService(d1).setServiceParent(self.node1)
        FireMeService(d2).setServiceParent(self.node2)
        ms = MultiService()
        self.node1.setServiceParent(ms)
        self.node2.setServiceParent(ms)
        ms.startService()

        @inlineCallbacks
        def _clean():
            yield ms.stopService()
            self.flushLoggedErrors(CancelledError)

        self.addCleanup(_clean)
        yield gatherResults([d1, d2])
        self.store.queuer = self.node1
Esempio n. 14
0
 def thunk(operation):
     return inTransaction(transactionCreator, operation)