def clean_junk_locks(self): for path, dirnames, filenames in walk_on_path(self.path): filenames = filenames or [] for dirname in dirnames: folder_path = join_paths(path, dirname) for filename in get_dir_filenames(folder_path): if not filename.startswith('.'): filenames.append(join_paths(dirname, filename)) for filename in filenames: filename = to_string(filename) if filename.startswith('.'): continue file_path = join_paths(path, filename) if '.' in filename: # Delete inactive positions locks binary = get_file_binary(file_path, mode='r') if binary: info = binary.split() if len(info) >= 2 and info[0] == DOMAIN_NAME and maybe_integer(info[1]): try: getpgid(int(info[1])) except OSError as error: if error.errno is errno.ESRCH: remove_file_quietly( file_path, retries=self.retries, retry_errno=self.retry_errno) else: # Clean locks wait list # Get last modified time, to check if file as been updated in the process modified_time = file_modified_time(file_path) if modified_time: binary = get_file_binary(file_path, mode='r') if binary: # Find alive locks keep_codes = binary.splitlines() for i, line in enumerate(keep_codes): info = line.split() if len(info) >= 2 and info[0] == DOMAIN_NAME and maybe_integer(info[1]): try: getpgid(int(info[1])) except OSError as error: if error.errno is errno.ESRCH: # Add empty line to keep position number keep_codes[i] = '' # Check if file as been updated in the process last_modified_time = file_modified_time(file_path) if last_modified_time and modified_time == last_modified_time: if not any(keep_codes): remove_file_quietly(file_path) else: with open(file_path, 'w') as f: f.write(NEW_LINE.join(keep_codes))
def get_token_info(self, token_256): file_path = self.get_token_file_path(token_256) binary = get_file_binary(file_path, mode='r') if binary: return loads(binary) else: return {}
def _get_binary(self, path, expire=MARKER): if expire is MARKER: expire = self.expire if expire: modified_time = file_modified_time(path) if not modified_time: return None elif (modified_time + expire) < NOW_TIME(): self._delete_path(path) return None return get_file_binary(path, mode='rb', retries=self.retries, retry_errno=self.retry_errno)
def delete_session_key_tokens(self, session_key_256): file_path = self.get_reference_file_path(session_key_256) if isfile(file_path): temporary_file_path = self.get_reference_file_path(session_key_256 + '.tmp') move_file(file_path, temporary_file_path) binary = get_file_binary(temporary_file_path, mode='r') if binary: tokens_to_delete = binary.splitlines() if tokens_to_delete: for token_256 in set(tokens_to_delete): if token_256: token_file_path = self.get_token_file_path(token_256) remove_file_quietly(token_file_path) # Remove references file remove_file_quietly(temporary_file_path) return True
def session_is_alive(self, session_key_256): reference_path = self.get_reference_file_path(session_key_256) binary = get_file_binary(reference_path) if binary: tokens = binary.splitlines() if tokens: now = NOW_TIME() for token_256 in set(tokens): if token_256: token_path = self.get_token_file_path(token_256) last_read_time = last_read_file_time(token_path) if last_read_time: if now <= (last_read_time + self.token_expire_seconds): return True else: # Remove token garbage remove_file_quietly(token_path) else: # Remove session reference remove_file_quietly(reference_path) return False
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)