def check_object_writer(self): class FakeConnection(ConnectionBase): def new_oid(self): return ROOT_OID def note_access(self, obj): pass connection = FakeConnection() self.s=s=ObjectWriter(connection) x = Persistent() assert x._p_connection == None x._p_oid = ROOT_OID x._p_connection = connection assert s._persistent_id(x) == (ROOT_OID, Persistent) x._p_connection = FakeConnection() # connection of x no longer matches connection of s. raises(ValueError, s._persistent_id, x) x.a = Persistent() assert s.get_state(x), ( '\x80\x02cdurus.persistent\nPersistent\nq\x01.\x80\x02}q\x02U' '\x01aU\x08\x00\x00\x00\x00\x00\x00\x00\x00q\x03h\x01\x86Qs.', '\x00\x00\x00\x00\x00\x00\x00\x00') assert list(s.gen_new_objects(x)) == [x, x.a] # gen_new_objects() can only be called once. raises(RuntimeError, s.gen_new_objects, 3) s.close()
def commit(self): """ If there are any changes, try to store them, and raise ConflictError if there are any invalid oids saved or if there are any invalid oids for non-ghost objects. """ if not self.changed: self._sync() else: if self.invalid_oids: # someone is trying to commit after a read or write conflict raise ConflictError(list(self.invalid_oids)) self.storage.begin() new_objects = {} for oid, changed_object in self.changed.iteritems(): writer = ObjectWriter(self) try: for obj in writer.gen_new_objects(changed_object): oid = obj._p_oid if oid in new_objects: continue elif oid not in self.changed: new_objects[oid] = obj self.cache[oid] = obj data, refs = writer.get_state(obj) self.storage.store(oid, pack_record(oid, data, refs)) obj._p_set_status_saved() finally: writer.close() try: self.storage.end(self._handle_invalidations) except ConflictError, exc: for oid, obj in new_objects.iteritems(): del self.cache[oid] self.loaded_oids.discard(oid) obj._p_set_status_unsaved() obj._p_oid = None obj._p_connection = None raise self.changed.clear()
def commit(self): """ If there are any changes, try to store them, and raise WriteConflictError if there are any invalid oids saved or if there are any invalid oids for non-ghost objects. """ if not self.changed: self._sync() else: assert not self.invalid_oids, "still conflicted: missing abort()" self.storage.begin() new_objects = {} for oid, changed_object in iteritems(self.changed): writer = ObjectWriter(self) try: for obj in writer.gen_new_objects(changed_object): oid = obj._p_oid if oid in new_objects: continue elif oid not in self.changed: new_objects[oid] = obj self.cache[oid] = obj data, refs = writer.get_state(obj) self.storage.store(oid, pack_record(oid, data, refs)) obj._p_set_status_saved() finally: writer.close() try: self.storage.end(self._handle_invalidations) except ConflictError: for oid, obj in iteritems(new_objects): obj._p_oid = None del self.cache[oid] obj._p_set_status_unsaved() obj._p_connection = None raise self.changed.clear() self.shrink_cache() self.transaction_serial += 1
def __init__(self, storage, cache_size=8000): """(storage:Storage, cache_size:int=8000) Make a connection to `storage`. Set the target number of non-ghosted persistent objects to keep in the cache at `cache_size`. """ assert isinstance(storage, Storage) self.storage = storage self.reader = ObjectReader(self) self.changed = {} self.invalid_oids = Set() self.loaded_oids = Set() try: storage.load(ROOT_OID) except KeyError: self.storage.begin() writer = ObjectWriter(self) data, refs = writer.get_state(PersistentDict()) writer.close() self.storage.store(ROOT_OID, pack_record(ROOT_OID, data, refs)) self.storage.end(self._handle_invalidations) self.new_oid = storage.new_oid # needed by serialize self.cache = Cache(cache_size) self.cache.hold(self.get_root())