def remove_reference(self, name, expire=MARKER): file_path = self.get_reference_path(name) temporary_file_path = file_path + '.' + make_uuid_hash() move_file(file_path, temporary_file_path, retries=self.retries, retry_errno=self.retry_errno) references = self._get_references(temporary_file_path, name='') if name in references: references.remove(name) # Validate if references still exists if references: if expire is MARKER: # Dont use expire, we only need to know if file exists expire = None for name in references: path = self.get_file_path(name) if not self._contains(path, expire=expire): references.remove(name) if references: references = maybe_list(references) references.append(b_linesep) put_binary_on_file( file_path, binary=bytes_join(b_linesep, references), mode='ab', retries=self.retries, retry_errno=self.retry_errno) self._delete_path(temporary_file_path)
def lock(self, name, timeout=MARKER, delete_lock_on_timeout=MARKER): name_256 = self.format_name(name) lock_code = make_uuid_hash() lock_name = '%s %s %s' % (DOMAIN_NAME, PROCESS_ID, lock_code) position = None while position is None: self.memcache.add(name_256, '0') position = self.memcache.incr(name_256) if position is 1: # Me first! Thank you! return None # Define expire time expire_time = None if timeout is MARKER: timeout = self.timeout if timeout: expire_time = NOW_TIME() + int(timeout) # Lock my wait position position_name_256 = self.format_position_name(name_256, position) self.memcache.set(position_name_256, lock_name) # Wait until my locked position is cleaned while self._contains(position_name_256): sleep(0.1) if expire_time and NOW_TIME() > expire_time: # Im done! No more wait for me! if not self.memcache.delete(position_name_256): # Wait.. after all.. its show time! return None if delete_lock_on_timeout is MARKER: delete_lock_on_timeout = self.delete_lock_on_timeout if delete_lock_on_timeout: self.unlock(name) # Sorry, you need to do everything again return self.lock(name, timeout=timeout, delete_lock_on_timeout=delete_lock_on_timeout) else: # Clean invalid locks! if self.clean_junk_locks(name_256): # Go again return self.lock(name, timeout=timeout, delete_lock_on_timeout=delete_lock_on_timeout) message = 'Timeout (%ss) on lock "%s". Delete (%s*) to unlock' % (timeout, name, name_256) raise LockTimeout(message, name_256) self.memcache.delete(position_name_256)
def make_key(self): return make_uuid_hash()
def lock(self, name, timeout=MARKER, delete_lock_on_timeout=MARKER): path = self.get_file_path(name) lock_code = make_uuid_hash() lock_name = '%s %s %s' % (DOMAIN_NAME, PROCESS_ID, lock_code) lock_name_to_file = lock_name + NEW_LINE position = None while position is None: # Enter on wait list put_binary_on_file(path, lock_name_to_file, mode='a', retries=self.retries, retry_errno=self.retry_errno) # Find my wait position binary = get_file_binary(path, mode='r', retries=self.retries, retry_errno=self.retry_errno) if binary: for i, code in enumerate(binary.splitlines()): if code.split()[-1] == lock_code: position = i break if position is 0: # Me first! Thank you! return # Define expire time expire_time = None if timeout is MARKER: timeout = self.timeout if timeout: expire_time = NOW_TIME() + int(timeout) # Lock my wait position position_path = '%s.%s' % (path, position) put_binary_on_file(position_path, lock_name, retries=self.retries, retry_errno=self.retry_errno) # Wait until my locked position is cleaned while isfile(position_path): sleep(0.1) if expire_time and NOW_TIME() > expire_time: # Im done! No more wait for me! try: remove_file(position_path) except OSError as error: if error.errno is errno.ENOENT: # Wait.. after all.. its show time! return None else: raise if delete_lock_on_timeout is MARKER: delete_lock_on_timeout = self.delete_lock_on_timeout if delete_lock_on_timeout: self.unlock(name) # Sorry, you need to do everything again return self.lock(name, timeout=timeout, delete_lock_on_timeout=delete_lock_on_timeout) else: # Clean locks! self.clean_junk_locks_as_daemon() message = 'Timeout (%ss) on lock "%s". Delete (%s*) to unlock' % (timeout, name, path) raise LockTimeout(message, position_path) remove_file_quietly(position_path, retries=self.retries, retry_errno=self.retry_errno)