def lock(self, hash_key, timeout=60): """Acquires the lock on hash_key or raises LockError The return value is a context manager object that will automatically release the lock on hash_key when it exits. locks are not nestable, they can only be acquired once. If the lock cannot be acquired a back-off strategy is implemented using random waits up to a total maximum of *timeout* seconds. If the lock still cannot be obtained :py:class:`LockError` is raised.""" owner = "%s_%i" % (self.magic, threading.current_thread().ident) with self.entity_set.OpenCollection() as locks: tnow = time.time() tstop = tnow + timeout twait = 0 while tnow < tstop: time.sleep(twait) lock = locks.new_entity() lock['hash'].SetFromValue(hash_key) lock['owner'].SetFromValue(owner) lock['created'].SetFromValue(TimePoint.FromNowUTC()) try: locks.insert_entity(lock) return LockStoreContext(self, hash_key) except edm.ConstraintError: pass try: lock = locks[hash_key] except KeyError: # someone deleted the lock, go straight round again twait = 0 tnow = time.time() continue # has this lock expired? locktime = lock['created'].value.WithZone(zDirection=0) if locktime.get_unixtime() + self.lock_timeout < tnow: # use optimistic locking lock['owner'].SetFromValue(owner) try: locks.update_entity(lock) logging.warn( "LockingBlockStore removed stale lock " "on %s", hash_key) return LockStoreContext(self, hash_key) except KeyError: twait = 0 tnow = time.time() continue except edm.ConstraintError: pass twait = random.randint(0, timeout // 5) tnow = time.time() logging.error("LockingBlockStore: timeout locking %s", hash_key) raise LockError
def flush(self): if self._bdirty: # the current block is dirty, write it out data = self._bdata[:self._btop] if data: block = self.blocks[self._bnum] if block.exists: self.ss.update_block(block, str(data)) else: self.blocks[self._bnum] = self.ss.store_block( self.stream, self._bnum, data) if self.size != self.stream['size'].value: self.stream['size'].SetFromValue(self.size) now = TimePoint.FromNowUTC() self.stream['modified'].SetFromValue(now) self.stream.Update() self._bdirty = False
def new_stream(self, mimetype=http.MediaType('application', 'octet-stream')): """Creates a new stream in the store. mimetype A :py:class:`~pyslet.rfc2616.MimeType` object Returns a stream entity which is an :py:class:`~pyslet.odata2.csdl.Entity` instance. The stream is identified by the stream entity's key which you can store elsewhere as a reference.""" with self.stream_set.OpenCollection() as streams: stream = streams.new_entity() if not isinstance(mimetype, http.MediaType): mimetype = http.MediaType.FromString(mimetype) stream['mimetype'].SetFromValue(str(mimetype)) now = TimePoint.FromNowUTC() stream['size'].SetFromValue(0) stream['created'].SetFromValue(now) stream['modified'].SetFromValue(now) streams.insert_entity(stream) return stream