Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZODB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
ZODB
Commits
824123b8
Commit
824123b8
authored
Apr 23, 2010
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cross-database wekrefs weren't handled correctly.
https://bugs.launchpad.net/zodb/+bug/435547
parent
8fd960bc
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
105 additions
and
13 deletions
+105
-13
src/CHANGES.txt
src/CHANGES.txt
+4
-0
src/ZODB/ConflictResolution.py
src/ZODB/ConflictResolution.py
+5
-1
src/ZODB/ConflictResolution.txt
src/ZODB/ConflictResolution.txt
+11
-1
src/ZODB/serialize.py
src/ZODB/serialize.py
+27
-10
src/persistent/wref.py
src/persistent/wref.py
+58
-1
No files found.
src/CHANGES.txt
View file @
824123b8
...
...
@@ -22,6 +22,10 @@ Bugs Fixed
https://bugs.launchpad.net/zodb/+bug/428039
- cross-database wekrefs weren't handled correctly.
https://bugs.launchpad.net/zodb/+bug/435547
- The mkzeoinst script was fixed to tell people to
install and use the mkzeoinstance script. :)
...
...
src/ZODB/ConflictResolution.py
View file @
824123b8
...
...
@@ -116,13 +116,17 @@ class PersistentReference(object):
# 'm' = multi_persistent: (database_name, oid, klass)
# 'n' = multi_oid: (database_name, oid)
# 'w' = persistent weakref: (oid)
# or persistent weakref: (oid, database_name)
# else it is a weakref: reference_type
if
reference_type
==
'm'
:
self
.
database_name
,
self
.
oid
,
self
.
klass
=
data
[
1
]
elif
reference_type
==
'n'
:
self
.
database_name
,
self
.
oid
=
data
[
1
]
elif
reference_type
==
'w'
:
try
:
self
.
oid
,
=
data
[
1
]
except
ValueError
:
self
.
oid
,
self
.
database_name
=
data
[
1
]
self
.
weak
=
True
else
:
assert
len
(
data
)
==
1
,
'unknown reference format'
...
...
src/ZODB/ConflictResolution.txt
View file @
824123b8
...
...
@@ -474,6 +474,16 @@ integrity issues.
>>> ref3.weak
True
>>> ref3a = PersistentReference(['w', ('my_oid', 'other_db')])
>>> ref3a.oid
'my_oid'
>>> print ref3a.klass
None
>>> ref3a.database_name
'other_db'
>>> ref3a.weak
True
>>> ref4 = PersistentReference(['m', ('other_db', 'my_oid', 'my_class')])
>>> ref4.oid
'my_oid'
...
...
@@ -508,7 +518,7 @@ integrity issues.
>>> ref1 == ref1 and ref2 == ref2 and ref4 == ref4 and ref5 == ref5
True
>>> ref3 == ref3 and ref6 == ref6 # weak references
>>> ref3 == ref3 and ref
3a == ref3a and ref
6 == ref6 # weak references
True
Non-weak references with the same oid and database_name are equal.
...
...
src/ZODB/serialize.py
View file @
824123b8
...
...
@@ -100,7 +100,8 @@ oid
The following reference types are defined:
'w'
Persistent weak reference. The arguments consist of an oid.
Persistent weak reference. The arguments consist of an oid
and optionally a database name.
The following are planned for the future:
...
...
@@ -298,8 +299,8 @@ class ObjectWriter:
oid
=
obj
.
oid
if
oid
is
None
:
obj
=
obj
()
# get the referenced object
oid
=
obj
.
_p_oid
target
=
obj
()
# get the referenced object
oid
=
target
.
_p_oid
if
oid
is
None
:
# Here we are causing the object to be saved in
# the database. One could argue that we shouldn't
...
...
@@ -308,10 +309,16 @@ class ObjectWriter:
# assume that the object will be added eventually.
oid
=
self
.
_jar
.
new_oid
()
obj
.
_p_jar
=
self
.
_jar
obj
.
_p_oid
=
oid
self
.
_stack
.
append
(
obj
)
target
.
_p_jar
=
self
.
_jar
target
.
_p_oid
=
oid
self
.
_stack
.
append
(
target
)
obj
.
oid
=
oid
obj
.
dm
=
target
.
_p_jar
obj
.
database_name
=
obj
.
dm
.
db
().
database_name
if
obj
.
dm
is
self
.
_jar
:
return
[
'w'
,
(
oid
,
)]
else
:
return
[
'w'
,
(
oid
,
obj
.
database_name
)]
# Since we have an oid, we have either a persistent instance
...
...
@@ -530,10 +537,20 @@ class ObjectReader:
loaders
[
'm'
]
=
load_multi_persistent
def
load_persistent_weakref
(
self
,
oid
):
def
load_persistent_weakref
(
self
,
oid
,
database_name
=
None
):
obj
=
WeakRef
.
__new__
(
WeakRef
)
obj
.
oid
=
oid
if
database_name
is
None
:
obj
.
dm
=
self
.
_conn
else
:
obj
.
database_name
=
database_name
try
:
obj
.
dm
=
self
.
_conn
.
get_connection
(
database_name
)
except
KeyError
:
# XXX Not sure what to do here. It seems wrong to
# fail since this is a weak reference. For now we'll
# just pretend that the target object has gone.
pass
return
obj
loaders
[
'w'
]
=
load_persistent_weakref
...
...
@@ -649,7 +666,7 @@ def referencesf(p, oids=None):
return
oids
oid_klass_loaders
=
{
'w'
:
lambda
oid
:
None
,
'w'
:
lambda
oid
,
database_name
=
None
:
None
,
}
def
get_refs
(
a_pickle
):
...
...
src/persistent/wref.py
View file @
824123b8
...
...
@@ -99,6 +99,61 @@ class WeakRef(object):
Always explicitly close databases: :)
>>> db.close()
>>> del ob, ref, db, conn1, conn2, conn3
When multiple databases are in use, a weakref in one database may
point to an object in a different database. Let's create two new
databases to demonstrate this.
>>> dbA = ZODB.tests.util.DB(
... database_name = 'dbA',
... )
>>> dbB = ZODB.tests.util.DB(
... database_name = 'dbB',
... databases = dbA.databases,
... )
>>> connA1 = dbA.open()
>>> connB1 = connA1.get_connection('dbB')
Now create and add a new object and a weak reference, and add them
to different databases.
>>> ob = ZODB.tests.MinPO.MinPO()
>>> ref = WeakRef(ob)
>>> connA1.root()['ob'] = ob
>>> connA1.add(ob)
>>> connB1.root()['ref'] = ref
>>> transaction.commit()
After a succesful commit, the reference should know the oid,
database name and connection of the object.
>>> ref.oid == ob._p_oid
True
>>> ref.database_name == 'dbA'
True
>>> ref.dm is ob._p_jar is connA1
True
If we open new connections, we should be able to use the reference.
>>> connA2 = dbA.open()
>>> connB2 = connA2.get_connection('dbB')
>>> ref2 = connB2.root()['ref']
>>> ob2 = connA2.root()['ob']
>>> ref2() is ob2
True
>>> ref2.oid == ob2._p_oid
True
>>> ref2.database_name == 'dbA'
True
>>> ref2.dm is ob2._p_jar is connA2
True
Always explicitly close databases: :)
>>> dbA.close()
>>> dbB.close()
"""
...
...
@@ -110,6 +165,8 @@ class WeakRef(object):
self
.
_v_ob
=
ob
self
.
oid
=
ob
.
_p_oid
self
.
dm
=
ob
.
_p_jar
if
self
.
dm
is
not
None
:
self
.
database_name
=
self
.
dm
.
db
().
database_name
def
__call__
(
self
):
try
:
...
...
@@ -117,7 +174,7 @@ class WeakRef(object):
except
AttributeError
:
try
:
self
.
_v_ob
=
self
.
dm
[
self
.
oid
]
except
KeyError
:
except
(
KeyError
,
AttributeError
)
:
return
None
return
self
.
_v_ob
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment