def state(self, oid, serial, prfactory, p=''): p = p or self.loadSerial(oid, serial) p = self._crs_untransform_record_data(p) file = BytesIO(p) unpickler = PersistentUnpickler(find_global, prfactory.persistent_load, file) unpickler.load() # skip the class tuple return unpickler.load()
def is_blob_record(record): """Check whether a database record is a blob record. This is primarily intended to be used when copying data from one storage to another. """ if record and (b'ZODB.blob' in record): unpickler = PersistentUnpickler(find_global_Blob, None, BytesIO(record)) try: return unpickler.load() is Blob except (MemoryError, KeyboardInterrupt, SystemExit): raise except Exception: pass return False
def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle, committedData=b''): # class_tuple, old, committed, newstate = ('',''), 0, 0, 0 klass = 'n/a' try: prfactory = PersistentReferenceFactory() newpickle = self._crs_untransform_record_data(newpickle) file = BytesIO(newpickle) unpickler = PersistentUnpickler(find_global, prfactory.persistent_load, file) meta = unpickler.load() if isinstance(meta, tuple): klass = meta[0] newargs = meta[1] or () if isinstance(klass, tuple): klass = find_global(*klass) else: klass = meta newargs = () if klass in _unresolvable: raise ConflictError inst = klass.__new__(klass, *newargs) try: resolve = inst._p_resolveConflict except AttributeError: _unresolvable[klass] = 1 raise ConflictError oldData = self.loadSerial(oid, oldSerial) if not committedData: committedData = self.loadSerial(oid, committedSerial) newstate = unpickler.load() old = state(self, oid, oldSerial, prfactory, oldData) committed = state(self, oid, committedSerial, prfactory, committedData) resolved = resolve(old, committed, newstate) file = BytesIO() pickler = PersistentPickler(persistent_id, file, _protocol) pickler.dump(meta) pickler.dump(resolved) return self._crs_transform_record_data(file.getvalue()) except (ConflictError, BadClassName) as e: logger.debug("Conflict resolution on %s failed with %s: %s", klass, e.__class__.__name__, str(e)) except: # If anything else went wrong, catch it here and avoid passing an # arbitrary exception back to the client. The error here will mask # the original ConflictError. A client can recover from a # ConflictError, but not necessarily from other errors. But log # the error so that any problems can be fixed. logger.exception( "Unexpected error while trying to resolve conflict on %s", klass) raise ConflictError(oid=oid, serials=(committedSerial, oldSerial), data=newpickle)
def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle, committedData=b''): # class_tuple, old, committed, newstate = ('',''), 0, 0, 0 klass = 'n/a' try: prfactory = PersistentReferenceFactory() newpickle = self._crs_untransform_record_data(newpickle) file = BytesIO(newpickle) unpickler = PersistentUnpickler( find_global, prfactory.persistent_load, file) meta = unpickler.load() if isinstance(meta, tuple): klass = meta[0] newargs = meta[1] or () if isinstance(klass, tuple): klass = find_global(*klass) else: klass = meta newargs = () if klass in _unresolvable: raise ConflictError inst = klass.__new__(klass, *newargs) try: resolve = inst._p_resolveConflict except AttributeError: _unresolvable[klass] = 1 raise ConflictError oldData = self.loadSerial(oid, oldSerial) if not committedData: committedData = self.loadSerial(oid, committedSerial) newstate = unpickler.load() old = state(self, oid, oldSerial, prfactory, oldData) committed = state(self, oid, committedSerial, prfactory, committedData) resolved = resolve(old, committed, newstate) file = BytesIO() pickler = PersistentPickler(persistent_id, file, _protocol) pickler.dump(meta) pickler.dump(resolved) return self._crs_transform_record_data(file.getvalue()) except (ConflictError, BadClassName) as e: logger.debug( "Conflict resolution on %s failed with %s: %s", klass, e.__class__.__name__, str(e)) except: # If anything else went wrong, catch it here and avoid passing an # arbitrary exception back to the client. The error here will mask # the original ConflictError. A client can recover from a # ConflictError, but not necessarily from other errors. But log # the error so that any problems can be fixed. logger.exception( "Unexpected error while trying to resolve conflict on %s", klass) raise ConflictError(oid=oid, serials=(committedSerial, oldSerial), data=newpickle)