예제 #1
0
    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))
예제 #2
0
 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 {}
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
    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)