Exemple #1
0
 def tpc_abort(self, transaction):
     """Abort current transaction."""
     txn_context = self._txn_container.pop(transaction)
     if txn_context is None:
         return
     ttid = txn_context['ttid']
     p = Packets.AbortTransaction(ttid)
     getConnForNode = self.cp.getConnForNode
     # cancel transaction one all those nodes
     nodes = txn_context['involved_nodes']
     nodes |= txn_context['checked_nodes']
     for node in nodes:
         conn = getConnForNode(node)
         if conn is None:
             continue
         try:
             conn.notify(p)
         except:
             logging.exception(
                 'Exception in tpc_abort while notifying'
                 'storage node %r of abortion, ignoring.', conn)
     conn = self.master_conn
     if conn is not None:
         conn.notify(p)
     # We don't need to flush queue, as it won't be reused by future
     # transactions (deleted on next line & indexed by transaction object
     # instance).
     self.dispatcher.forget_queue(txn_context['queue'], flush_queue=False)
Exemple #2
0
 def notifyTransactionAborted(self, ttid, uuids):
     uuid_set = self.getStorageReadySet()
     uuid_set.intersection_update(uuids)
     if uuid_set:
         p = Packets.AbortTransaction(ttid, ())
         getByUUID = self.nm.getByUUID
         for uuid in uuid_set:
             getByUUID(uuid).send(p)
Exemple #3
0
 def tpc_abort(self, transaction):
     """Abort current transaction."""
     txn_context = self._txn_container.pop(transaction)
     if txn_context is None:
         return
     # We want that the involved nodes abort a transaction after any
     # other packet sent by the client for this transaction. IOW, if we
     # already have a connection with a storage node, potentially with
     # a pending write, aborting only via the master may lead to a race
     # condition. The consequence would be that storage nodes lock oids
     # forever.
     p = Packets.AbortTransaction(txn_context.ttid, ())
     for conn in txn_context.conn_dict.itervalues():
         if conn is not None:
             try:
                 conn.send(p)
             except ConnectionClosed:
                 pass
     # Because we want to be sure that the involved nodes are notified,
     # we still have to send the full list to the master. Most of the
     # time, the storage nodes get 2 AbortTransaction packets, and the
     # second one is rarely useful. Another option would be that the
     # storage nodes keep a list of aborted transactions, but the
     # difficult part would be to avoid a memory leak.
     try:
         notify = self.master_conn.send
     except AttributeError:
         pass
     else:
         try:
             notify(
                 Packets.AbortTransaction(txn_context.ttid,
                                          list(txn_context.conn_dict)))
         except ConnectionClosed:
             pass
     # We don't need to flush queue, as it won't be reused by future
     # transactions (deleted on next line & indexed by transaction object
     # instance).
     self.dispatcher.forget_queue(txn_context.queue, flush_queue=False)
Exemple #4
0
 def abortTransaction(self, conn, tid, uuid_list):
     # Consider a failure when the connection between the storage and the
     # client breaks while the answer to the first write is sent back.
     # In other words, the client can not know the exact set of nodes that
     # know this transaction, and it sends us all nodes it considered for
     # writing.
     # We must also add those that are waiting for this transaction to be
     # finished (returned by tm.abort), because they may have join the
     # cluster after that the client started to abort.
     app = self.app
     involved = app.tm.abort(tid, conn.getUUID())
     involved.update(uuid_list)
     involved.intersection_update(app.getStorageReadySet())
     if involved:
         p = Packets.AbortTransaction(tid, ())
         getByUUID = app.nm.getByUUID
         for involved in involved:
             getByUUID(involved).send(p)