[Zope-dev] Call Profiler strangeness - lots of ZODB transactions

Richard Jones rjones@ekit-inc.com
Tue, 9 Apr 2002 09:27:38 +1000


On Tue, 26 Mar 2002 21:29, Toby Dickenson wrote:
> On Tue, 26 Mar 2002 15:30:56 +1100, Richard Jones
>
> <rjones@ekit-inc.com> wrote:
> >I'm investigating why our product ZODB is growing when it shouldn't. I've
> >found that the undo log has entries in it every five minutes saying
> >"Installed product CallProfiler by Zope". More infrequently (not
> > regularly) we also have "Installed product ZOracleDA by Zope".
>
> Was zope restarting (or being restarted) every five minutes?

No, but it is being pinged. By that, I mean that we have a script that tries 
to access the ZEO server every five minutes to make sure it's all OK. The 
script does the following::

  import sys, os
  sys.path.append('/app/zope/zopecontrol_code/')
  sys.path.insert(0, '/app/zope/zopecontrol_code/lib/python')
  os.environ['ZEOPORT'] = '8076'
  os.environ['ZEOHOST'] = 'devhost1.off.ekorp.com'
  import Zope
  # now do stuff with the Zope.app() (we don't actually have to do anything
  # to trigger the ZODB note generation - the import is enough)

Now, the problem lies in the way that the CallProfiler gets itself into the 
Control Panel. This code was copied from the LeakFinder product, so I assume 
it'll have the same problem. The code is::

 def installControlPanel(context, panelClass):
    from App.ApplicationManager import ApplicationManager
    from Acquisition import aq_base
    app = context._ProductContext__app
    cp = app.Control_Panel
    id = panelClass.id
    if 0: # Enable to clean up the control panel.
        try: del cp._objects
        except: pass
    cp.id # Unghostify.
    if hasattr(cp, id):
        return cp._getOb(id)
    if cp.__dict__.has_key('_objects'):
        # _objects has been overridden.  We have to persist.
        existing = getattr(aq_base(cp), id, None)
        if existing is None or existing.__class__ != panelClass:
            cp._setObject(id, panelClass())
    else:
        # Don't persist what we don't have to.
        objects = ApplicationManager._objects
        objects = filter(lambda o, id=id: o['id'] != id, objects)
        ApplicationManager._objects = objects + (
            {'id':id, 'meta_type':panelClass.meta_type},)
        try: delattr(cp, id)
        except: pass
        setattr(ApplicationManager, id, panelClass())
    return cp._getOb(id)

Where panelClass is my Product's class.

When the ping script imports Zope, the product is installed. If it's 
installed as a "regular" product, using context.registerClass, all is OK. If 
it is installed using the above function, I get ZODB transaction notes of the 
form "Installed product CallProfiler by Zope   2002-04-08 11:14:10 PM".

It's all a bit black magic for me though. I honestly don't know why half of 
the function above actually exists. I'm going to keep looking though, but if 
someone could help, I'd be extremely grateful.


    Richard