|
| 1 | +# -*- coding: utf-8 -*- |
1 | 2 | ##############################################################################
|
2 | 3 | #
|
3 | 4 | # Copyright (c) Zope Corporation and Contributors.
|
@@ -108,11 +109,16 @@ def __init__(self, name=None, base=None, changes=None,
|
108 | 109 | if close_changes_on_close is None:
|
109 | 110 | close_changes_on_close = False
|
110 | 111 | else:
|
| 112 | + self._temporary_changes = False |
111 | 113 | if ZODB.interfaces.IBlobStorage.providedBy(changes):
|
112 | 114 | zope.interface.alsoProvides(self, ZODB.interfaces.IBlobStorage)
|
113 | 115 | if close_changes_on_close is None:
|
114 | 116 | close_changes_on_close = True
|
115 | 117 |
|
| 118 | + if ZODB.interfaces.IExternalGC.providedBy(changes): |
| 119 | + zope.interface.alsoProvides(self, ZODB.interfaces.IExternalGC) |
| 120 | + self.deleteObject = self._storeDelete |
| 121 | + |
116 | 122 | self.changes = changes
|
117 | 123 | self.close_changes_on_close = close_changes_on_close
|
118 | 124 |
|
@@ -376,6 +382,40 @@ def store(self, oid, serial, data, version, transaction):
|
376 | 382 | else:
|
377 | 383 | self.changes.store(oid, serial, data, '', transaction)
|
378 | 384 |
|
| 385 | + # _storeDelete serves deleteObject when .changes implements IExternalGC. |
| 386 | + def _storeDelete(self, oid, oldserial, transaction): |
| 387 | + if transaction is not self._transaction: |
| 388 | + raise ZODB.POSException.StorageTransactionError(self, transaction) |
| 389 | + |
| 390 | + # oldserial ∈ changes -> changes.deleteObject |
| 391 | + baseHead = self.base.lastTransaction() |
| 392 | + if oldserial > baseHead: |
| 393 | + self.changes.deleteObject(oid, oldserial, transaction) |
| 394 | + return |
| 395 | + |
| 396 | + # oldserial ∈ base -> find out it is indeed the latest there and then |
| 397 | + # call changes.deleteObject(oldserial=z64) |
| 398 | + |
| 399 | + _, serial = ZODB.utils.loadAt(self.changes, oid, self.changes.lastTransaction()) |
| 400 | + if serial != ZODB.utils.z64: |
| 401 | + # object has data or deletion record in changes |
| 402 | + raise ZODB.POSException.ConflictError(oid=oid, serials=(serial, oldserial)) |
| 403 | + |
| 404 | + _, serial = ZODB.utils.loadAt(self.base, oid, baseHead) |
| 405 | + if serial != oldserial: |
| 406 | + raise ZODB.POSException.ConflictError(oid=oid, serials=(serial, oldserial)) |
| 407 | + |
| 408 | + # object has no data/deletion record in changes and its latest revision in base == oldserial |
| 409 | + # -> changes.deleteObject(oldserial=z64) + correct oldserial back on conflict. |
| 410 | + try: |
| 411 | + self.changes.deleteObject(oid, ZODB.utils.z64, transaction) |
| 412 | + except ZODB.POSException.ConflictError as e: |
| 413 | + assert len(e.serials) == 2 |
| 414 | + assert e.serials[1] == ZODB.utils.z64 |
| 415 | + e.serials = (e.serials[0], oldserial) |
| 416 | + raise |
| 417 | + |
| 418 | + |
379 | 419 | def storeBlob(self, oid, oldserial, data, blobfilename, version,
|
380 | 420 | transaction):
|
381 | 421 | assert version=='', "versions aren't supported"
|
|
0 commit comments