Commit 46815aff authored by Barry Warsaw's avatar Barry Warsaw

_zaprevision(): When garbage collecting an object, we need to do a

little more work.  First, we need to delete all the entries for
oid+vid records in the currentVersions table, then if we delete all
thosey vid entries, garbage collect the version->vid and vid->version
tables.

pack(): Fix a slight misunderstanding of the semantics; if an object
isn't pointed to by root object (i.e. the magic \0\0\0\0\0\0\0\0 oid),
then it's current record doesn't keep it alive.
parent aa3de9c1
...@@ -4,7 +4,7 @@ See Minimal.py for an implementation of Berkeley storage that does not support ...@@ -4,7 +4,7 @@ See Minimal.py for an implementation of Berkeley storage that does not support
undo or versioning. undo or versioning.
""" """
# $Revision: 1.20 $ # $Revision: 1.21 $
__version__ = '0.1' __version__ = '0.1'
import struct import struct
...@@ -891,6 +891,7 @@ class Full(BerkeleyBase): ...@@ -891,6 +891,7 @@ class Full(BerkeleyBase):
# decref any pickles it points to. For everything else, we'll do it # decref any pickles it points to. For everything else, we'll do it
# in the most efficient manner possible. # in the most efficient manner possible.
tids = [] tids = []
vids = []
for oid in collectables: for oid in collectables:
self._serials.delete(oid) self._serials.delete(oid)
self._refcounts.delete(oid) self._refcounts.delete(oid)
...@@ -902,21 +903,18 @@ class Full(BerkeleyBase): ...@@ -902,21 +903,18 @@ class Full(BerkeleyBase):
try: try:
rec = c.set(oid) rec = c.set(oid)
while rec and rec[0][:8] == oid: while rec and rec[0][:8] == oid:
# Remember the transaction ids so we can clean up the # Remember the transaction and version ids so we can clean
# txnoids table below. Note that we don't record the vids # up the txnoids table and the currentVersions table below.
# because now that we don't have destructive undo, vids.append(rec[1][:8]) # the 1st 8-bytes of value
# _zaprevisions() can only be called during a pack() and tids.append(rec[0][8:]) # second half of the key
# it is impossible to pack current records (and hence
# currentVersions).
tids.append(rec[0][8:]) # second 1/2 of the key
self._zaprevision(rec[0], referencesf) self._zaprevision(rec[0], referencesf)
rec = c.next() rec = c.next()
finally: finally:
c.close() c.close()
# Delete all the txnoids entries that referenced this oid # Delete all the txnoids entries that referenced this oid
for tid in tids:
c = self._txnoids.cursor() c = self._txnoids.cursor()
try: try:
for tid in tids:
rec = c.set_both(tid, oid) rec = c.set_both(tid, oid)
while rec: while rec:
# Although unlikely, it is possible that an object got # Although unlikely, it is possible that an object got
...@@ -925,6 +923,24 @@ class Full(BerkeleyBase): ...@@ -925,6 +923,24 @@ class Full(BerkeleyBase):
rec = c.next_dup() rec = c.next_dup()
finally: finally:
c.close() c.close()
# And delete all version entries w/ records containing oid
c = self._currentVersions.cursor()
try:
for vid in vids:
rec = c.set_both(vid, oid)
while rec:
c.delete()
rec = c.next_dup()
finally:
c.close()
# Now, for each vid, delete the versions->vid and vid->versions
# mapping if we've deleted all references to this vid
for vid in vids:
if self._currentVersions.get(vid):
continue
version = self._versions[vid]
self._versions.delete(vid)
self._vids.delete(version)
def pack(self, t, referencesf): def pack(self, t, referencesf):
# BAW: This doesn't play nicely if you enable the `debugging revids' # BAW: This doesn't play nicely if you enable the `debugging revids'
...@@ -978,6 +994,19 @@ class Full(BerkeleyBase): ...@@ -978,6 +994,19 @@ class Full(BerkeleyBase):
if key[8:] == current: if key[8:] == current:
continue continue
self._zaprevision(key, referencesf) self._zaprevision(key, referencesf)
# Now look and see if the object has a reference count of
# zero, and if so garbage collect it.
refcounts = self._refcounts.get(oid)
if not refcounts:
# The current revision should be the only revision of this
# object that exists, otherwise it's refcounts shouldn't
# be zero.
self._zaprevision(oid+current, referencesf)
# And delete a few other records that _zaprevisions()
# doesn't clean up
self._serials.delete(oid)
if refcounts <> None:
self._refcounts.delete(oid)
finally: finally:
if c: if c:
c.close() c.close()
...@@ -990,6 +1019,7 @@ class Full(BerkeleyBase): ...@@ -990,6 +1019,7 @@ class Full(BerkeleyBase):
This means they can be garbage collected, with all necessary cascading This means they can be garbage collected, with all necessary cascading
reference counting performed reference counting performed
""" """
# BAW: this is broken -- make it look like the end of pack()
self._lock_acquire() self._lock_acquire()
c = None c = None
try: try:
......
...@@ -4,7 +4,7 @@ See Minimal.py for an implementation of Berkeley storage that does not support ...@@ -4,7 +4,7 @@ See Minimal.py for an implementation of Berkeley storage that does not support
undo or versioning. undo or versioning.
""" """
# $Revision: 1.20 $ # $Revision: 1.21 $
__version__ = '0.1' __version__ = '0.1'
import struct import struct
...@@ -891,6 +891,7 @@ class Full(BerkeleyBase): ...@@ -891,6 +891,7 @@ class Full(BerkeleyBase):
# decref any pickles it points to. For everything else, we'll do it # decref any pickles it points to. For everything else, we'll do it
# in the most efficient manner possible. # in the most efficient manner possible.
tids = [] tids = []
vids = []
for oid in collectables: for oid in collectables:
self._serials.delete(oid) self._serials.delete(oid)
self._refcounts.delete(oid) self._refcounts.delete(oid)
...@@ -902,21 +903,18 @@ class Full(BerkeleyBase): ...@@ -902,21 +903,18 @@ class Full(BerkeleyBase):
try: try:
rec = c.set(oid) rec = c.set(oid)
while rec and rec[0][:8] == oid: while rec and rec[0][:8] == oid:
# Remember the transaction ids so we can clean up the # Remember the transaction and version ids so we can clean
# txnoids table below. Note that we don't record the vids # up the txnoids table and the currentVersions table below.
# because now that we don't have destructive undo, vids.append(rec[1][:8]) # the 1st 8-bytes of value
# _zaprevisions() can only be called during a pack() and tids.append(rec[0][8:]) # second half of the key
# it is impossible to pack current records (and hence
# currentVersions).
tids.append(rec[0][8:]) # second 1/2 of the key
self._zaprevision(rec[0], referencesf) self._zaprevision(rec[0], referencesf)
rec = c.next() rec = c.next()
finally: finally:
c.close() c.close()
# Delete all the txnoids entries that referenced this oid # Delete all the txnoids entries that referenced this oid
for tid in tids:
c = self._txnoids.cursor() c = self._txnoids.cursor()
try: try:
for tid in tids:
rec = c.set_both(tid, oid) rec = c.set_both(tid, oid)
while rec: while rec:
# Although unlikely, it is possible that an object got # Although unlikely, it is possible that an object got
...@@ -925,6 +923,24 @@ class Full(BerkeleyBase): ...@@ -925,6 +923,24 @@ class Full(BerkeleyBase):
rec = c.next_dup() rec = c.next_dup()
finally: finally:
c.close() c.close()
# And delete all version entries w/ records containing oid
c = self._currentVersions.cursor()
try:
for vid in vids:
rec = c.set_both(vid, oid)
while rec:
c.delete()
rec = c.next_dup()
finally:
c.close()
# Now, for each vid, delete the versions->vid and vid->versions
# mapping if we've deleted all references to this vid
for vid in vids:
if self._currentVersions.get(vid):
continue
version = self._versions[vid]
self._versions.delete(vid)
self._vids.delete(version)
def pack(self, t, referencesf): def pack(self, t, referencesf):
# BAW: This doesn't play nicely if you enable the `debugging revids' # BAW: This doesn't play nicely if you enable the `debugging revids'
...@@ -978,6 +994,19 @@ class Full(BerkeleyBase): ...@@ -978,6 +994,19 @@ class Full(BerkeleyBase):
if key[8:] == current: if key[8:] == current:
continue continue
self._zaprevision(key, referencesf) self._zaprevision(key, referencesf)
# Now look and see if the object has a reference count of
# zero, and if so garbage collect it.
refcounts = self._refcounts.get(oid)
if not refcounts:
# The current revision should be the only revision of this
# object that exists, otherwise it's refcounts shouldn't
# be zero.
self._zaprevision(oid+current, referencesf)
# And delete a few other records that _zaprevisions()
# doesn't clean up
self._serials.delete(oid)
if refcounts <> None:
self._refcounts.delete(oid)
finally: finally:
if c: if c:
c.close() c.close()
...@@ -990,6 +1019,7 @@ class Full(BerkeleyBase): ...@@ -990,6 +1019,7 @@ class Full(BerkeleyBase):
This means they can be garbage collected, with all necessary cascading This means they can be garbage collected, with all necessary cascading
reference counting performed reference counting performed
""" """
# BAW: this is broken -- make it look like the end of pack()
self._lock_acquire() self._lock_acquire()
c = None c = None
try: try:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment