[Zope] Database connectors

Maciej Wisniowski maciej.wisniowski at coig.katowice.pl
Tue Nov 21 03:56:49 EST 2006


> In fact, the "_v_database_connection" is *NOT* necessary to
> abort(rollback) commit the transaction:
>   
I have procedure WYJATEK in Oracle that
simply raises exception.
I've created StoredProcedure in Zope called
'wyjatek' and navigated to 'Test' page.
Then I've restarted Zope, and after restart I've
just hit 'Test' button.
Below is full pdb session (Zope running with one thread only) starting
from :
/opt/Zope/2.8.8/lib/python/transaction/_transaction.py(492)abort()

In short: there are two resource managers registered:
1. <Connection at b62f228c>
2. <MultiObjectResourceAdapter for <Procedure at wyjatek> at -1241707860>

When 1. is aborted, then in it's _abort method I have:
    self._registered_objects == [<Procedure at wyjatek>]
and the code below is executed:

for obj in self._registered_objects:
    oid = obj._p_oid
    (...)
    self._cache.invalidate(oid)


Later, 2. is being aborted and in SP.py _abort I have:

self._v_db.db.rollback()
AttributeError: '_v_db'

So there is no rollback to Oracle.

SP.py __call__ is:
        self._register()  # uses:
transaction.get().register(Surrogate(self))
        try:
            # Note, this does not do result promotion like the DA query will
            # which is probably bad.  OracleDates in particular look like
            # DateTimes but arent at all the same!
            results = apply ( self._v_proc, args, kw )
            return results
            #return self._lobConvert(results)
        except:          
            logger.error('Error in dco2 procedure')
            self._v_proc = None
            raise                          # Reraise error

Is this because of: self._cache.invalidate(oid)?

Maciej Wisniowski


Full pdb session:


2006-11-21 08:04:16 INFO Zope Ready to handle requests
2006-11-21 08:04:16 DEBUG txn.16386 new transaction
2006-11-21 08:04:16 INFO _transaction abort
2006-11-21 08:04:16 INFO _transaction []
(...)
2006-11-21 08:04:24 DEBUG txn.16386 new transaction
2006-11-21 08:04:24 DEBUG DCOracle2 - DCOracle2.py Created new DCO2
connection <Products.DCOracle2.DCOracle2.DCOracle2.connection instance
at 0xb5fd0dac>
2006-11-21 08:04:24 ERROR DCOracle2 - SP.py Error in dco2 procedure
2006-11-21 08:04:24 ERROR Zope.SiteErrorLog
http://eurolinux:8091/testOracleDRTest/wyjatek/manage_testZOracleStoredProcedure
Traceback (most recent call last):
  File "/opt/Zope/2.8.8/lib/python/ZPublisher/Publish.py", line 114, in
publish
    request, bind=1)
  File "/opt/Zope/2.8.8/lib/python/ZPublisher/mapply.py", line 88, in mapply
    if debug is not None: return debug(object,args,context)
  File "/opt/Zope/2.8.8/lib/python/ZPublisher/Publish.py", line 40, in
call_object
    result=apply(object,args) # Type s<cr> to step into published object.
  File "/opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py",
line 341, in manage_testZOracleStoredProcedure
    v = apply(self,[],REQUEST.form)
  File "/opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py",
line 312, in __call__
    results = apply(self._v_proc,args,kw)
  File
"/opt/Zope/instancje/oracletest/Products/DCOracle2/DCOracle2/DCOracle2.py",
line 1563, in __call__
    cursor.execute(sql,__plist=args)
  File
"/opt/Zope/instancje/oracletest/Products/DCOracle2/DCOracle2/DCOracle2.py",
line 1023, in execute
    result = self._cursor.execute()
DatabaseError: (20001, 'ORA-20001: BlaBlaBla\nORA-06512: at
"TEST.WYJATEKFUNC", line 6\nORA-06512: at line 1')
2006-11-21 08:04:24 INFO _transaction abort
2006-11-21 08:04:24 INFO _transaction [<Connection at b62f228c>,
<MultiObjectResourceAdapter for <Procedure at wyjatek> at -1241707860>]
--Return--
> /usr/local/lib/python2.3/pdb.py(992)set_trace()->None
-> Pdb().set_trace()
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(492)abort()
-> for rm in self._resources:
(Pdb) l
487             self._synchronizers.map(lambda s: s.beforeCompletion(self))
488
489             tb = None
490             logger.info(str(self._resources))
491             import pdb;pdb.set_trace()
492  ->         for rm in self._resources:
493                 try:
494                     rm.abort(self)
495                 except:
496                     if tb is None:
497                         t, v, tb = sys.exc_info()
(Pdb) p self._resources
[<Connection at b62f228c>, <MultiObjectResourceAdapter for <Procedure at
wyjatek> at -1241707860>]
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(493)abort()
-> try:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(494)abort()
-> rm.abort(self)
(Pdb) s
--Call--
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(338)abort()
-> def abort(self, transaction):
(Pdb) l
333        
##########################################################################
334
335        
##########################################################################
336         # Data manager (ISavepointDataManager) methods
337
338  ->     def abort(self, transaction):
339             """Abort a transaction and forget all changes."""
340
341             # The order is important here.  We want to abort registered
342             # objects before we process the cache.  Otherwise, we
may un-add
343             # objects added in savepoints.  If they've been modified
since
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(348)abort()
-> self._abort()
(Pdb) l
343             # objects added in savepoints.  If they've been modified
since
344             # the savepoint, then they won't have _p_oid or _p_jar after
345             # they've been unadded. This will make the code in _abort
346             # confused.
347
348  ->         self._abort()
349
350             if self._savepoint_storage is not None:
351                 self._abort_savepoint()
352
353             self._tpc_cleanup()
(Pdb) s
--Call--
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(355)_abort()
-> def _abort(self):
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(358)_abort()
-> for obj in self._registered_objects:
(Pdb) l
353             self._tpc_cleanup()
354
355         def _abort(self):
356             """Abort a transaction and forget all changes."""
357
358  ->         for obj in self._registered_objects:
359                 oid = obj._p_oid
360                 assert oid is not None
361                 if oid in self._added:
362                     del self._added[oid]
363                     del obj._p_jar
(Pdb) p self._registered_objects
[<Procedure at wyjatek>]
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(359)_abort()
-> oid = obj._p_oid
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(360)_abort()
-> assert oid is not None
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(361)_abort()
-> if oid in self._added:
(Pdb) p self._added
{}
(Pdb) l
356             """Abort a transaction and forget all changes."""
357
358             for obj in self._registered_objects:
359                 oid = obj._p_oid
360                 assert oid is not None
361  ->             if oid in self._added:
362                     del self._added[oid]
363                     del obj._p_jar
364                     del obj._p_oid
365                 else:
366
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(386)_abort()
-> self._cache.invalidate(oid)
(Pdb) l
381                     # go ahead and invalidate now.  Fortunately, it's
382                     # pretty unlikely that the object we are
invalidating
383                     # was invalidated by another thread, so the risk
of a
384                     # reread is pretty low.
385
386  ->                 self._cache.invalidate(oid)
387
388         def _tpc_cleanup(self):
389             """Performs cleanup operations to support tpc_finish and
tpc_abort."""
390             self._conflicts.clear()
391             if not self._synch:
(Pdb) s
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(358)_abort()
-> for obj in self._registered_objects:
(Pdb) n
--Return--
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(358)_abort()->None
-> for obj in self._registered_objects:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(350)abort()
-> if self._savepoint_storage is not None:
(Pdb) l
345             # they've been unadded. This will make the code in _abort
346             # confused.
347
348             self._abort()
349
350  ->         if self._savepoint_storage is not None:
351                 self._abort_savepoint()
352
353             self._tpc_cleanup()
354
355         def _abort(self):
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(353)abort()
-> self._tpc_cleanup()
(Pdb) s
--Call--
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(388)_tpc_cleanup()
-> def _tpc_cleanup(self):
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(390)_tpc_cleanup()
-> self._conflicts.clear()
(Pdb) l
385
386                     self._cache.invalidate(oid)
387
388         def _tpc_cleanup(self):
389             """Performs cleanup operations to support tpc_finish and
tpc_abort."""
390  ->         self._conflicts.clear()
391             if not self._synch:
392                 self._flush_invalidations()
393             self._needs_to_join = True
394             self._registered_objects = []
395
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(391)_tpc_cleanup()
-> if not self._synch:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(393)_tpc_cleanup()
-> self._needs_to_join = True
(Pdb) n
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(394)_tpc_cleanup()
-> self._registered_objects = []
(Pdb) n
--Return--
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(394)_tpc_cleanup()->None
-> self._registered_objects = []
(Pdb) n
--Return--
> /opt/Zope/2.8.8/lib/python/ZODB/Connection.py(353)abort()->None
-> self._tpc_cleanup()
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(492)abort()
-> for rm in self._resources:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(493)abort()
-> try:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(494)abort()
-> rm.abort(self)
(Pdb) p rm
<MultiObjectResourceAdapter for <Procedure at wyjatek> at -1241707860>
(Pdb) s
--Call--
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(563)abort()
-> def abort(self, txn):
(Pdb) l
558                 self.ncommitted += 1
559
560         def tpc_vote(self, txn):
561             self.manager.tpc_vote(txn)
562
563  ->     def abort(self, txn):
564             tb = None
565             for o in self.objects:
566                 try:
567                     self.manager.abort(o, txn)
568                 except:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(564)abort()
-> tb = None
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(565)abort()
-> for o in self.objects:
(Pdb) p self.objects
[<Shared.DC.ZRDB.TM.Surrogate instance at 0xb5fd0c6c>]
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(566)abort()
-> try:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(567)abort()
-> self.manager.abort(o, txn)
(Pdb) s
--Call--
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(158)abort()
-> def abort(self, *ignored):
(Pdb) l
153
154             if self._v_finalize:
155                 try: self._finish()
156                 finally: self._v_registered=0
157
158  ->     def abort(self, *ignored):
159             try: self._abort()
160             finally: self._v_registered=0
161
162         tpc_abort = abort
163
(Pdb) p self._v_db
*** AttributeError: <exceptions.AttributeError instance at 0xb5fd09ec>
(Pdb) n
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(159)abort()
-> try: self._abort()
(Pdb) s
--Call--
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(219)_abort()
-> def _abort(self, *ignored):
(Pdb) l
214                 self._v_db.db.commit()
215             except Exception, e:
216                 logger.error( 'Exception in SP.py, _finish: %s' % (e) )
217                 print 'Exception in SP.py, _finish: %s' % (e)
218
219  ->     def _abort(self, *ignored):
220             try:
221                 logger.info('_abort')
222                 self._v_db.db.rollback()
223             except Exception, e:
224                 logger.error( 'Exception in SP.py, _abort: %s' % (e) )
(Pdb) p self._v_db
*** AttributeError: <exceptions.AttributeError instance at 0xb603988c>
(Pdb) n
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(220)_abort()
-> try:
(Pdb) n
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(221)_abort()
-> logger.info('_abort')
(Pdb) n
2006-11-21 08:08:18 INFO DCOracle2 - SP.py _abort
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(222)_abort()
-> self._v_db.db.rollback()
(Pdb) n
AttributeError: '_v_db'
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(222)_abort()
-> self._v_db.db.rollback()
(Pdb) l
217                 print 'Exception in SP.py, _finish: %s' % (e)
218
219         def _abort(self, *ignored):
220             try:
221                 logger.info('_abort')
222  ->             self._v_db.db.rollback()
223             except Exception, e:
224                 logger.error( 'Exception in SP.py, _abort: %s' % (e) )
225
226         def description(self):
227             if getattr(self,"_v_proc",None) is None: self._connect()
(Pdb) n
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(223)_abort()
-> except Exception, e:
(Pdb) n
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(224)_abort()
-> logger.error( 'Exception in SP.py, _abort: %s' % (e) )
(Pdb) n
2006-11-21 08:08:52 ERROR DCOracle2 - SP.py Exception in SP.py, _abort:
_v_db
--Return--
>
/opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(224)_abort()->None
-> logger.error( 'Exception in SP.py, _abort: %s' % (e) )
(Pdb) n
> /opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(160)abort()
-> finally: self._v_registered=0
(Pdb) n
--Return--
>
/opt/Zope/instancje/oracletest288/Products/DCOracle2/SP.py(160)abort()->None
-> finally: self._v_registered=0
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(565)abort()
-> for o in self.objects:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(575)abort()
-> if tb is not None:
(Pdb) n
--Return--
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(575)abort()->None
-> if tb is not None:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(492)abort()
-> for rm in self._resources:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(501)abort()
-> if self._manager:
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(502)abort()
-> self._manager.free(self)
(Pdb) l
497                         t, v, tb = sys.exc_info()
498                     self.log.error("Failed to abort resource
manager: %s",
499                                    rm, exc_info=sys.exc_info())
500
501             if self._manager:
502  ->             self._manager.free(self)
503
504             self._synchronizers.map(lambda s: s.afterCompletion(self))
505
506             self.log.debug("abort")
507
(Pdb) p self._manager
<transaction._manager.ThreadTransactionManager object at 0xb715aaec>
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(504)abort()
-> self._synchronizers.map(lambda s: s.afterCompletion(self))
(Pdb) n
> /opt/Zope/2.8.8/lib/python/transaction/_transaction.py(506)abort()
-> self.log.debug("abort")
(Pdb) c
2006-11-21 08:09:33 DEBUG txn.16386 abort
2006-11-21 08:09:33 DEBUG txn.16386 new transaction
2006-11-21 08:09:33 INFO _transaction abort
2006-11-21 08:09:33 INFO _transaction []
--Return--
> /usr/local/lib/python2.3/pdb.py(992)set_trace()->None
-> Pdb().set_trace()



More information about the Zope mailing list