1 | """ |
---|
2 | Ported to Python 3. |
---|
3 | """ |
---|
4 | |
---|
5 | import struct |
---|
6 | |
---|
7 | import attr |
---|
8 | |
---|
9 | from .lease_schema import ( |
---|
10 | v1_immutable, |
---|
11 | v2_immutable, |
---|
12 | ) |
---|
13 | |
---|
14 | @attr.s(frozen=True) |
---|
15 | class _Schema(object): |
---|
16 | """ |
---|
17 | Implement encoding and decoding for multiple versions of the immutable |
---|
18 | container schema. |
---|
19 | |
---|
20 | :ivar int version: the version number of the schema this object supports |
---|
21 | |
---|
22 | :ivar lease_serializer: an object that is responsible for lease |
---|
23 | serialization and unserialization |
---|
24 | """ |
---|
25 | version = attr.ib() |
---|
26 | lease_serializer = attr.ib() |
---|
27 | |
---|
28 | def header(self, max_size): |
---|
29 | # type: (int) -> bytes |
---|
30 | """ |
---|
31 | Construct a container header. |
---|
32 | |
---|
33 | :param max_size: the maximum size the container can hold |
---|
34 | |
---|
35 | :return: the header bytes |
---|
36 | """ |
---|
37 | # The second field -- the four-byte share data length -- is no longer |
---|
38 | # used as of Tahoe v1.3.0, but we continue to write it in there in |
---|
39 | # case someone downgrades a storage server from >= Tahoe-1.3.0 to < |
---|
40 | # Tahoe-1.3.0, or moves a share file from one server to another, |
---|
41 | # etc. We do saturation -- a share data length larger than 2**32-1 |
---|
42 | # (what can fit into the field) is marked as the largest length that |
---|
43 | # can fit into the field. That way, even if this does happen, the old |
---|
44 | # < v1.3.0 server will still allow clients to read the first part of |
---|
45 | # the share. |
---|
46 | return struct.pack(">LLL", self.version, min(2**32 - 1, max_size), 0) |
---|
47 | |
---|
48 | ALL_SCHEMAS = { |
---|
49 | _Schema(version=2, lease_serializer=v2_immutable), |
---|
50 | _Schema(version=1, lease_serializer=v1_immutable), |
---|
51 | } |
---|
52 | ALL_SCHEMA_VERSIONS = {schema.version for schema in ALL_SCHEMAS} |
---|
53 | NEWEST_SCHEMA_VERSION = max(ALL_SCHEMAS, key=lambda schema: schema.version) |
---|
54 | |
---|
55 | def schema_from_version(version): |
---|
56 | # (int) -> Optional[type] |
---|
57 | """ |
---|
58 | Find the schema object that corresponds to a certain version number. |
---|
59 | """ |
---|
60 | for schema in ALL_SCHEMAS: |
---|
61 | if schema.version == version: |
---|
62 | return schema |
---|
63 | return None |
---|