@@ -56,89 +56,177 @@ class CompressionLib:
5656
5757class Chunk (Object ):
5858
59- def __init__ (self , number , offset , url , length ):
59+ def __init__ (self , offset , url , length ):
6060 """
6161 Initialize a Chunk.
6262
63- :param int number: Chunk number.
6463 :param int offset: Chunk offset.
6564 :param str url: Signed URL.
6665 :param int length: Object length.
6766 """
6867 super ().__init__ (
69- number = number ,
7068 offset = offset ,
7169 url = url ,
7270 length = length
7371 )
7472
7573
76- class Metadata (Object ):
74+ class MetadataPart (Object ):
7775 """
78- CTERA Direct IO File Metadata
76+ CTERA Direct I/O File Metadata Part
77+
78+ :ivar int start: Starting offset.
79+ :ivar int end: Ending offset.
80+ :ivar int length: Length of the range in bytes.
81+ :ivar bool encrypted: Indicates whether the range data is encrypted.
82+ :ivar str encryption_key: Encryption key used for the range data.
83+ :ivar bool compressed: Indicates whether the range data is compressed.
84+ :ivar str compression_alg: Compression algorithm used for the range data.
85+ :ivar list[cterasdk.common.object.Object] chunks: List of Chunk Objects.
7986 """
80-
81- def __init__ (self , file_id , server_object ):
87+ def __init__ (self , offset , end , encrypted , encryption_key , compressed , compression_alg , chunks ):
8288 """
8389 Initialize a Direct IO metadata response object.
8490
85- :param int file_id: File ID.
86- :param cterasdk.common.object.Object server_object: Response Object.
91+ :param int offset: Starting offset.
92+ :param int end: Ending offset.
93+ :param bool encrypted: Indicates whether the file is encrypted.
94+ :param str encryption_key: Encryption key used for the file.
95+ :param bool compressed: Indicates whether the file is compressed.
96+ :param str compression_alg: Compression algorithm used for the file.
97+ :param list[cterasdk.common.object.Object] chunks: List of Chunk Objects.
8798 """
8899 super ().__init__ (
89- file_id = file_id ,
90- encrypted = server_object .encrypt_info .data_encrypted ,
91- compressed = server_object .compression_type != CompressionLib .Off ,
92- chunks = Metadata ._format_chunks (server_object .chunks )
100+ start = offset ,
101+ end = end ,
102+ length = (end - offset ) + 1 ,
103+ encrypted = encrypted ,
104+ encryption_key = encryption_key ,
105+ compressed = compressed ,
106+ compression_alg = compression_alg
93107 )
94- self .encryption_key = server_object .encrypt_info .wrapped_key if self .encrypted else None
95- self .compression_library = server_object .compression_type if self .compressed else None
96- last_chunk = self .chunks [- 1 ]
97- self .size = last_chunk .offset + last_chunk .length
108+ for chunk in chunks :
109+ self .chunks .append (Chunk (offset , chunk .url , chunk .len ))
110+ offset = offset + chunk .len
98111
99112 @staticmethod
100- def _format_chunks (server_object ):
113+ def from_server_object (server_object ):
114+ compressed = server_object .compression_type != CompressionLib .Off
115+ start , end = map (int , server_object .actual_blocks_range .range .split ('-' ))
116+ return MetadataPart (
117+ start ,
118+ end ,
119+ server_object .encrypt_info .data_encrypted ,
120+ server_object .encrypt_info .wrapped_key if server_object .encrypt_info .data_encrypted else None ,
121+ compressed ,
122+ server_object .compression_type if compressed else None
123+ )
124+
125+ def __repr__ (self ):
126+ return str (self )
127+
128+ def __str__ (self ):
129+ return (
130+ f"{ self .__class__ .__name__ } ("
131+ f"{{'start': { self .start } , "
132+ f"'end': { self .end } , "
133+ f"'encrypted': { self .encrypted } , "
134+ f"'compressed': { self .compressed } , "
135+ f"'length': { self .length } , "
136+ f"'chunks': { len (self .chunks )} }})"
137+ )
138+
139+
140+ class Metadata (Object ):
141+ """
142+ CTERA Direct I/O File Metadata
143+
144+ :ivar int file_id: File ID.
145+ :ivar int file_size: File Size.
146+ :ivar list[cterasdk.direct.types.MetadataPart] parts: List of Metadata Parts.
147+ :ivar bool encrypted: Indicates whether the range data is encrypted.
148+ :ivar str encryption_key: Encryption key used for the range data.
149+ :ivar bool compressed: Indicates whether the range data is compressed.
150+ :ivar str compression_alg: Compression algorithm used for the range data.
151+ """
152+ def __init__ (self , file_id , * parts ):
101153 """
102- Create Chunks .
154+ Initialize a Direct IO metadata response object .
103155
104156 :param int file_id: File ID.
105- :param cterasdk.common.object.Object server_object: Server response.
106- :param list[int] blocks: List of block numbers to retrieve.
107- :returns: Chunk objects
108- :rtype: list[cterasdk.direct.types.Chunk]
157+ :param list[cterasdk.direct.types.MetadataPart] parts: List of Metadata Parts.
109158 """
110- offset = 0
111- chunks = []
112- for number , chunk in enumerate (server_object , 1 ):
113- chunks .append (Chunk (number , offset , chunk .url , chunk .len ))
114- offset = offset + chunk .len
115- return chunks
159+ super ().__init__ (file_id = file_id , parts = parts )
160+
161+ @property
162+ def size (self ):
163+ return self .parts [0 ].actual_blocks_range .file_size
164+
165+ @property
166+ def encrypted (self ):
167+ return self .parts [0 ].encrypted
168+
169+ @property
170+ def encryption_key (self ):
171+ return self .parts [0 ].encryption_key
172+
173+ @property
174+ def compressed (self ):
175+ return self .parts [0 ].compressed
176+
177+ @property
178+ def compression_alg (self ):
179+ return self .parts [0 ].compression_alg
180+
181+ @property
182+ def start (self ):
183+ return self .parts [0 ].start
184+
185+ @property
186+ def end (self ):
187+ return self .parts [- 1 ].end
116188
117189 def serialize (self ):
118190 """
119- Serialize Direct IO metadata to a dictionary.
191+ Serialize Direct I/O metadata to a dictionary.
120192 """
121- x = copy .deepcopy (self )
122- if self .encrypted :
123- x .encryption_key = utils .utf8_decode (base64 .b64encode (self .encryption_key ))
124- return x
193+ chunks = []
194+ for part in self .parts :
195+ chunks .extend (part .chunks )
196+
197+ return {
198+ 'file_id' : self .file_id ,
199+ 'size' : self .size ,
200+ 'encrypted' : self .encrypted ,
201+ 'encryption_key' : utils .utf8_decode (base64 .b64encode (self .encryption_key )) if self .encrypted else None ,
202+ 'compressed' : self .compressed ,
203+ 'compression_alg' : self .compression_alg ,
204+ 'chunks' : chunks
205+ }
206+
207+ def __repr__ (self ):
208+ return str (self )
209+
210+ def __str__ (self ):
211+ d = self .serialize ()
212+ d .pop ('encryption_key' )
213+ d ['chunks' ] = len (d ['chunks' ])
214+ return d
125215
126216
127217class Block :
128218 """Block"""
129219
130- def __init__ (self , file_id , number , offset , data , length ):
220+ def __init__ (self , file_id , offset , data , length ):
131221 """
132222 Initialize a Block.
133223
134224 :param int file_id: File ID.
135- :param int number: Block number.
136225 :param int offset: Block offset.
137226 :param bytes data: Bytes
138227 :param int length: Block length.
139228 """
140229 self ._file_id = file_id
141- self ._number = number
142230 self ._offset = offset
143231 self ._data = data
144232 self ._length = length
@@ -147,10 +235,6 @@ def __init__(self, file_id, number, offset, data, length):
147235 def file_id (self ):
148236 return self ._file_id
149237
150- @property
151- def number (self ):
152- return self ._number
153-
154238 @property
155239 def offset (self ):
156240 return self ._offset
0 commit comments