Current File : //usr/lib64/python3.6/site-packages/borg/__pycache__/repository.cpython-36.pyc |
3
up�d. � @ s� d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZm Z d dl
mZ d dlm
Z
d dlmZ d dlmZ d dlmZ dd lT dd
lmZ ddlmZmZmZmZmZ ddlmZ dd
lmZ ddlmZ ddlmZ ddlm Z m!Z! ddlm"Z" ddl#m$Z$m%Z%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4 e(e5�Z'dZ6e7e6�Z8dZ9e7e9�e8k�s�t:�d Z;dZ<dZ=dZ>eee?�Z@G dd� d�ZAG dd� d�ZBeBjCjDd k�s�t:�dS )!� N)�hexlify� unhexlify)�defaultdict)�ConfigParser)�datetime)�partial)�islice� )�*)�NSIndex)�Error�ErrorWithTraceback�IntegrityError�format_file_size�parse_file_size)�Location)�ProgressIndicatorPercent)�
bin_to_hex)�hostname_is_unique)�secure_erase�safe_unlink)�msgpack)�Lock� LockError�
LockErrorT)�
create_logger)�LRUCache)�SaveFile�SyncFile�sync_dir�safe_fadvise)�crc32)�IntegrityCheckedFile�FileIntegrityErrors BORG_SEGs ATTICSEG� � c @ sb e Zd ZdZG dd� de�ZG dd� de�ZG dd� de�ZG dd � d e�ZG d
d� de�Z G dd
� d
e�Z
G dd� de�ZG dd� de�Z
G dd� de�ZG dd� de�ZG dd� de�Zd{dd�Zdd� Zdd � Zd!d"� Zd#d$� Zed%d&� �Zed'd(� �Zd)d*� Zd+d,� Zd-d.� Zd/d0� Zd1d2� Zd3d4� Zd5d6� Z d7d8� Z!d9d:� Z"d;d<� Z#d=d>� Z$d?d@� Z%dAdB� Z&d|dCdD�Z'dEdF� Z(d}dGdH�Z)dIdJ� Z*d~dKdL�Z+ddMdN�Z,dOdP� Z-dQdR� Z.dSdT� Z/dUdV� Z0dWdX� Z1d�dYdZ�Z2d[d\� Z3d�d]d^�Z4d_d`� Z5dadb� Z6dcdd� Z7dedf� Z8dgdh� Z9d�didj�Z:d�dkdl�Z;dmdn� Z<d�dodp�Z=d�dqdr�Z>d�dsdt�Z?dudv� Z@d�dwdx�ZAdydz� ZBdS )��
Repositorya�
Filesystem based transactional key value store
Transactionality is achieved by using a log (aka journal) to record changes. The log is a series of numbered files
called segments. Each segment is a series of log entries. The segment number together with the offset of each
entry relative to its segment start establishes an ordering of the log entries. This is the "definition" of
time for the purposes of the log.
Log entries are either PUT, DELETE or COMMIT.
A COMMIT is always the final log entry in a segment and marks all data from the beginning of the log until the
segment ending with the COMMIT as committed and consistent. The segment number of a segment ending with a COMMIT
is called the transaction ID of that commit, and a segment ending with a COMMIT is called committed.
When reading from a repository it is first checked whether the last segment is committed. If it is not, then
all segments after the last committed segment are deleted; they contain log entries whose consistency is not
established by a COMMIT.
Note that the COMMIT can't establish consistency by itself, but only manages to do so with proper support from
the platform (including the hardware). See platform.base.SyncFile for details.
A PUT inserts a key-value pair. The value is stored in the log entry, hence the repository implements
full data logging, meaning that all data is consistent, not just metadata (which is common in file systems).
A DELETE marks a key as deleted.
For a given key only the last entry regarding the key, which is called current (all other entries are called
superseded), is relevant: If there is no entry or the last entry is a DELETE then the key does not exist.
Otherwise the last PUT defines the value of the key.
By superseding a PUT (with either another PUT or a DELETE) the log entry becomes obsolete. A segment containing
such obsolete entries is called sparse, while a segment containing no such entries is called compact.
Sparse segments can be compacted and thereby disk space freed. This destroys the transaction for which the
superseded entries where current.
On disk layout:
dir/README
dir/config
dir/data/<X // SEGMENTS_PER_DIR>/<X>
dir/index.X
dir/hints.X
File system interaction
-----------------------
LoggedIO generally tries to rely on common behaviours across transactional file systems.
Segments that are deleted are truncated first, which avoids problems if the FS needs to
allocate space to delete the dirent of the segment. This mostly affects CoW file systems,
traditional journaling file systems have a fairly good grip on this problem.
Note that deletion, i.e. unlink(2), is atomic on every file system that uses inode reference
counts, which includes pretty much all of them. To remove a dirent the inodes refcount has
to be decreased, but you can't decrease the refcount before removing the dirent nor can you
decrease the refcount after removing the dirent. File systems solve this with a lock,
and by ensuring it all stays within the same FS transaction.
Truncation is generally not atomic in itself, and combining truncate(2) and unlink(2) is of
course never guaranteed to be atomic. Truncation in a classic extent-based FS is done in
roughly two phases, first the extents are removed then the inode is updated. (In practice
this is of course way more complex).
LoggedIO gracefully handles truncate/unlink splits as long as the truncate resulted in
a zero length file. Zero length segments are considered to not exist, while LoggedIO.cleanup()
will still get rid of them.
c @ s e Zd ZdZdS )zRepository.DoesNotExistzRepository {} does not exist.N)�__name__�
__module__�__qualname__�__doc__� r+ r+ �"/usr/lib64/python3.6/repository.py�DoesNotExist{ s r- c @ s e Zd ZdZdS )zRepository.AlreadyExistsz"A repository already exists at {}.N)r'