[Zope-dev] PANIC(300) ZODB storage error--shouldn't happen
Ross Boylan
RossBoylan@stanfordalumni.org
Mon, 17 Jan 2000 14:25:23 -0800
Here's the traceback for Error: release unlocked lock
Traceback (innermost last):
File V:\src\ZopeRoot\lib\python\ZPublisher\Publish.py, line 214, in
publish_module
File V:\src\ZopeRoot\lib\python\ZPublisher\Publish.py, line 179, in publish
File V:\src\ZopeRoot\lib\python\Zope\__init__.py, line 202, in
zpublisher_exception_hook
(Object: RoleManager)
File V:\src\ZopeRoot\lib\python\ZPublisher\Publish.py, line 169, in publish
File V:\src\ZopeRoot\lib\python\ZODB\Transaction.py, line 275, in commit
File V:\src\ZopeRoot\lib\python\ZODB\Connection.py, line 467, in tpc_finish
File V:\src\ZopeRoot\lib\python\ZODB\BaseStorage.py, line 202, in tpc_finish
(Object: V:\src\ZopeRoot/var/Data.fs)
The traceback appears in the browser, while the error message below appears
on the console. After this, the application is unresponsive.
The only reason I got a new connection was that I didn't know how to get
the old one (or if it was safe to reuse it). Is there a canonical way to
get Zope's connection? I tried again using Zope.app()._p_jar. (I had
thought Zope.app() returned an application wrapper, and gave up when it
didn't). This produces the connection, but leads to the same error.
Other points:
After this failure, the key of the object I am trying to insert appears in
my OrgUserDirectory, and the value is of the right type (OrgUser). But the
value has nothing in it. The standard Zope users do seem to be created
(see below).
I am able to create the error immediately by executing
get_transaction.commit() in the debugger after my code finishes its normal
execution.
I tried del root['OrgUser'] in hopes that a new one would work better. It
didn't.
Some files are hanging around var/, even after a regular shutdown, which
look a bit odd. Here's a listing:
Directory of V:\src\ZopeRoot\var
01/17/00 02:15p 144,466 Data.fs
01/17/00 02:18p 1,971 Data.fs.index
01/17/00 02:18p 3 Data.fs.lock
01/17/00 02:16p 0 Data.fs.tmp
12/04/99 12:30p <DIR> gadfly
01/17/00 02:16p 3 pcgi.pid
01/17/00 02:17p 374,745 Z2.log
01/17/00 02:16p 3 Z2.pid
10 File(s) 521,191 bytes
Here's the code I'm running, with some junk stripped out. The product
creates OrgUserFolder. Some dtml then sends that object addOrgUser. This
creates a regular zope user and then an OrgUserDirectory and an OrgUser,
and puts the latter in the former.
---------------------------------- __init__.py
-----------------------------------------------------------------
import OrgUser
def initialize(context):
try:
context.registerClass(
OrgUser.OrgUserFolder,
constructors=(OrgUser.manage_addUserFolder, )
)
[except clause omited]
---------------------------------
OrgUser.py-------------------------------------------------------------------
import Globals
from Globals import HTMLFile, MessageDialog
import Persistence
from AccessControl.User import UserFolder
import Zope # for app for database
manage_addUserForm = HTMLFile('addUser', globals())
class OrgUser(Persistence.Persistent):
"""Add additional information on the user"""
meta_type ='Org User'
id = 'Organizational_User'
title = 'Organizational User'
def __init__(self, user, email):
self.user = user
self.email = email
getOrgUserDirectory().addUser(self)
def getUserName(self):
return self.user.getUserName()
def addOrgUser(name, password, confirm, email, namespace, REQUEST=None ) :
"To be called from dtml. Use _ for namespace"
[code omitted--I couldn't figure out how to call it, and it seems not to be
active]
# class method for OrgUserDirectory
_my_Dir = None
def getOrgUserDirectory():
"Return the root directory for OrgUsers"
global _my_Dir
if not _my_Dir :
import pdb
pdb.set_trace()
conn = Zope.app()._p_jar
root = conn.root()
_my_Dir = root.get("OrgUser", None)
if _my_Dir :
print "Found directory"
else:
print "Creating directory"
root["OrgUser"] = OrgUserDirectory()
_my_Dir = root["OrgUser"]
return _my_Dir
class OrgUserDirectory(Persistence.PersistentMapping):
def __init__(self) :
print "Creating OrgUserDirectory"
Persistence.PersistentMapping.__init__(self)
def addUser(self, orgUser):
"Add indicated user to database"
name = orgUser.getUserName()
if self.has_key(name) :
raise "You can not add an existing user"
self[name] = orgUser
class OrgUserFolder(UserFolder):
"""Base class for UserFolder-like objects"""
meta_type='Org User Folder'
title ='Organizational User Folder'
manage_userInfo=HTMLFile('editUser',globals())
def addOrgUser(acl, name, password, confirm, email, REQUEST=None ) :
"To be called from dtml. "
print "passing bound addOrgUser"
roles = [] # to be decided
domains = []
result = acl._addUser(name, password, confirm, roles, domains)
#I think that if we don't pass request, it returns None if all well
if result :
return result # probably not right since management
user = acl.getUser(name)
orgUser = OrgUser(user, email)
return "I think we're done"
def manage_addUserFolder(self,dtself=None,REQUEST=None,**ignored):
""" """
f=OrgUserFolder()
self=self.this()
try: self._setObject('acl_users', f)
except: return MessageDialog(
title ='Item Exists',
message='This object already contains a User Folder',
action ='%s/manage_main' % REQUEST['URL1'])
self.__allow_groups__=f
if REQUEST: return self.manage_main(self,REQUEST,update_menu=1)
At 08:58 AM 1/17/00 -0500, Jim Fulton wrote:
>Ross Boylan wrote:
>>
>> Can anyone suggest how to avoid the following? Feel free to consider this
>> a bug report, if it is a bug.
>>
>> 2000-01-16T04:38:30 PANIC(300) ZODB A storage error occurred in the last
>> phase o
>> f a two-phase commit. This shouldn't happen. The application may be in a
>> hosed
>> state, so we will not allow transactions to commit from here on
>
>Was some sort of traceback displayed to go with this?
>The only time I've seen this is when running out of space.
>
>> This happens after some seemingly successful database activity. I believe
>> the error is triggered by the commit before returning to the browser. I
>> suspect I have opened a connection in a way that conflicts with the
>> existing one.
>>
>> I say, in some code which a form calls,
>> conn = Globals.DB.open()
>> root = conn.root()
>> _my_Dir = root.get("OrgUser", None)
>> if _my_Dir :
>> print "Found directory"
>> else:
>> print "Creating directory"
>> root["OrgUser"] = OrgUserDirectory() #subclass
of PersistentMapping
>> _my_Dir = root["OrgUser"]
>> I then add an object to _my_dir, using dictionary protocols.
>
>This is incomplete. I see nothing so far to indicate a problem,
>but I don't see what else you've done. Why do you open a new connection?
>If you just want to get the root object, you can get the root object for the
>connection of some existing persistent object with:
>
> anExistingPersistentObject._p_jar.root()
>
>The attribute '_p_jar' is the database connection for a persistent object.
>
>If you open a new connection, you need to make sure you close it.
>
>> The zope session is started with -D. running Zope 2.1.1 on win32.
>>
>> It may also be relevant that my function returns a plain string to the
>> browser.
>
>Nah.
>
>Jim
>
>--
>Jim Fulton mailto:jim@digicool.com Python Powered!
>Technical Director (888) 344-4332 http://www.python.org
>Digital Creations http://www.digicool.com http://www.zope.org
>
>Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
>address may not be added to any commercial mail list with out my
>permission. Violation of my privacy with advertising or SPAM will
>result in a suit for a MINIMUM of $500 damages/incident, $1500 for
>repeats.
>