@@ -97,13 +97,122 @@ impl crate::application::CoLink {
97
97
Ok ( chunk_paths_string)
98
98
}
99
99
100
+ async fn _store_chunks_compatibility_mode (
101
+ & self ,
102
+ payload : & [ u8 ] ,
103
+ key_name : & str ,
104
+ ) -> Result < i32 , Error > {
105
+ let mut offset = 0 ;
106
+ let mut chunk_id = 0 ;
107
+ while offset < payload. len ( ) {
108
+ let chunk_size = if offset + CHUNK_SIZE > payload. len ( ) {
109
+ payload. len ( ) - offset
110
+ } else {
111
+ CHUNK_SIZE
112
+ } ;
113
+ self . update_entry (
114
+ & format ! ( "{}:{}" , key_name, chunk_id) ,
115
+ & payload[ offset..offset + chunk_size] ,
116
+ )
117
+ . await ?;
118
+ offset += chunk_size;
119
+ chunk_id += 1 ;
120
+ }
121
+ Ok ( chunk_id)
122
+ }
123
+
124
+ async fn _append_chunks_compatibility_mode (
125
+ & self ,
126
+ chunk_len : i32 ,
127
+ payload : & [ u8 ] ,
128
+ key_name : & str ,
129
+ ) -> Result < i32 , Error > {
130
+ let last_chunk_id = chunk_len - 1 ;
131
+ let mut last_chunk = self
132
+ . read_entry ( & format ! ( "{}:{}" , key_name, last_chunk_id, ) )
133
+ . await ?;
134
+ let mut offset = 0 ;
135
+ let mut chunk_id = chunk_len;
136
+ if last_chunk. len ( ) < CHUNK_SIZE {
137
+ let chunk_size = if payload. len ( ) < CHUNK_SIZE - last_chunk. len ( ) {
138
+ payload. len ( )
139
+ } else {
140
+ CHUNK_SIZE - last_chunk. len ( )
141
+ } ;
142
+ last_chunk. append ( & mut payload[ ..chunk_size] . to_vec ( ) ) ;
143
+ self . update_entry ( & format ! ( "{}:{}" , key_name, last_chunk_id) , & last_chunk)
144
+ . await ?;
145
+ offset = chunk_size;
146
+ }
147
+ while offset < payload. len ( ) {
148
+ let chunk_size = if offset + CHUNK_SIZE > payload. len ( ) {
149
+ payload. len ( ) - offset
150
+ } else {
151
+ CHUNK_SIZE
152
+ } ;
153
+ self . update_entry (
154
+ & format ! ( "{}:{}" , key_name, chunk_id) ,
155
+ & payload[ offset..offset + chunk_size] ,
156
+ )
157
+ . await ?;
158
+ offset += chunk_size;
159
+ chunk_id += 1 ;
160
+ }
161
+ Ok ( chunk_id)
162
+ }
163
+
164
+ async fn _delete_chunks_compatibility_mode ( & self , key_name : & str ) -> Result < String , Error > {
165
+ let metadata_key = format ! ( "{}:chunk_metadata" , key_name) ;
166
+ let chunk_len = self . read_entry ( & metadata_key) . await ?;
167
+ let chunk_len = String :: from_utf8_lossy ( & chunk_len) . parse :: < i32 > ( ) ?;
168
+ let res = self . delete_entry ( & metadata_key) . await ?;
169
+ for i in 0 ..chunk_len {
170
+ self . delete_entry ( & format ! ( "{}:{}" , key_name, i) ) . await ?;
171
+ }
172
+ Ok ( res)
173
+ }
174
+
175
+ async fn _chunk_lock_compatibility_mode ( & self , key_name : & str ) -> Result < ( ) , Error > {
176
+ loop {
177
+ if self
178
+ . create_entry ( & format ! ( "{}:chunk_lock" , key_name) , b"" )
179
+ . await
180
+ . is_ok ( )
181
+ {
182
+ return Ok ( ( ) ) ;
183
+ }
184
+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_millis ( 100 ) ) . await ;
185
+ }
186
+ }
187
+
188
+ async fn _chunk_unlock_compatibility_mode ( & self , key_name : & str ) -> Result < ( ) , Error > {
189
+ self . delete_entry ( & format ! ( "{}:chunk_lock" , key_name) )
190
+ . await ?;
191
+ Ok ( ( ) )
192
+ }
193
+
100
194
#[ async_recursion]
101
195
pub ( crate ) async fn _create_entry_chunk (
102
196
& self ,
103
197
key_name : & str ,
104
198
payload : & [ u8 ] ,
105
199
) -> Result < String , Error > {
106
200
let metadata_key = format ! ( "{}:chunk_metadata" , key_name) ;
201
+ if key_name. contains ( '$' ) {
202
+ self . _chunk_lock_compatibility_mode ( key_name) . await ?;
203
+ if let Err ( e) = self . create_entry ( & metadata_key, b"0" ) . await {
204
+ self . _chunk_unlock_compatibility_mode ( key_name) . await ?;
205
+ return Err ( e) ;
206
+ }
207
+ let chunk_len = self
208
+ . _store_chunks_compatibility_mode ( payload, key_name)
209
+ . await ?;
210
+ let res = self
211
+ . update_entry ( & metadata_key, chunk_len. to_string ( ) . as_bytes ( ) )
212
+ . await ?;
213
+ self . _chunk_unlock_compatibility_mode ( key_name) . await ?;
214
+ return Ok ( res) ;
215
+ }
107
216
// lock the metadata entry to prevent simultaneous writes
108
217
let lock_token = self . lock ( & metadata_key) . await ?;
109
218
// use a closure to prevent locking forever caused by errors
@@ -114,7 +223,7 @@ impl crate::application::CoLink {
114
223
let chunk_paths_string = self . _check_chunk_paths_size ( chunk_paths) ?;
115
224
// store the chunk paths in the metadata entry and update metadata
116
225
let response = self
117
- . create_entry ( & metadata_key, & chunk_paths_string. into_bytes ( ) )
226
+ . create_entry ( & metadata_key, chunk_paths_string. as_bytes ( ) )
118
227
. await ?;
119
228
Ok :: < String , Error > ( response)
120
229
}
@@ -126,6 +235,22 @@ impl crate::application::CoLink {
126
235
#[ async_recursion]
127
236
pub ( crate ) async fn _read_entry_chunk ( & self , key_name : & str ) -> Result < Vec < u8 > , Error > {
128
237
let metadata_key = format ! ( "{}:chunk_metadata" , key_name) ;
238
+ if key_name. contains ( '$' ) {
239
+ self . _chunk_lock_compatibility_mode ( key_name) . await ?;
240
+ let res = async {
241
+ let chunk_len = self . read_entry ( & metadata_key) . await ?;
242
+ let chunk_len = String :: from_utf8_lossy ( & chunk_len) . parse :: < i32 > ( ) ?;
243
+ let mut payload = Vec :: new ( ) ;
244
+ for i in 0 ..chunk_len {
245
+ let mut res = self . read_entry ( & format ! ( "{}:{}" , key_name, i) ) . await ?;
246
+ payload. append ( & mut res) ;
247
+ }
248
+ Ok :: < Vec < u8 > , Error > ( payload)
249
+ }
250
+ . await ;
251
+ self . _chunk_unlock_compatibility_mode ( key_name) . await ?;
252
+ return res;
253
+ }
129
254
let metadata_response = self . read_entry ( & metadata_key) . await ?;
130
255
let payload_string = String :: from_utf8 ( metadata_response) ?;
131
256
let user_id = self . get_user_id ( ) ?;
@@ -149,6 +274,18 @@ impl crate::application::CoLink {
149
274
payload : & [ u8 ] ,
150
275
) -> Result < String , Error > {
151
276
let metadata_key = format ! ( "{}:chunk_metadata" , key_name) ;
277
+ if key_name. contains ( '$' ) {
278
+ self . _chunk_lock_compatibility_mode ( key_name) . await ?;
279
+ let _ = self . _delete_chunks_compatibility_mode ( key_name) . await ;
280
+ let chunk_len = self
281
+ . _store_chunks_compatibility_mode ( payload, key_name)
282
+ . await ?;
283
+ let res = self
284
+ . update_entry ( & metadata_key, chunk_len. to_string ( ) . as_bytes ( ) )
285
+ . await ?;
286
+ self . _chunk_unlock_compatibility_mode ( key_name) . await ?;
287
+ return Ok ( res) ;
288
+ }
152
289
// lock the metadata entry to prevent simultaneous writes
153
290
let lock_token = self . lock ( & metadata_key) . await ?;
154
291
// use a closure to prevent locking forever caused by errors
@@ -159,7 +296,7 @@ impl crate::application::CoLink {
159
296
let chunk_paths_string = self . _check_chunk_paths_size ( chunk_paths) ?;
160
297
// update the metadata entry
161
298
let response = self
162
- . update_entry ( & metadata_key, & chunk_paths_string. into_bytes ( ) )
299
+ . update_entry ( & metadata_key, chunk_paths_string. as_bytes ( ) )
163
300
. await ?;
164
301
Ok :: < String , Error > ( response)
165
302
}
@@ -175,6 +312,19 @@ impl crate::application::CoLink {
175
312
payload : & [ u8 ] ,
176
313
) -> Result < String , Error > {
177
314
let metadata_key = format ! ( "{}:chunk_metadata" , key_name) ;
315
+ if key_name. contains ( '$' ) {
316
+ self . _chunk_lock_compatibility_mode ( key_name) . await ?;
317
+ let chunk_len = self . read_entry ( & metadata_key) . await ?;
318
+ let chunk_len = String :: from_utf8_lossy ( & chunk_len) . parse :: < i32 > ( ) ?;
319
+ let new_chunk_len = self
320
+ . _append_chunks_compatibility_mode ( chunk_len, payload, key_name)
321
+ . await ?;
322
+ let res = self
323
+ . update_entry ( & metadata_key, new_chunk_len. to_string ( ) . as_bytes ( ) )
324
+ . await ?;
325
+ self . _chunk_unlock_compatibility_mode ( key_name) . await ?;
326
+ return Ok ( res) ;
327
+ }
178
328
// lock the metadata entry to prevent simultaneous writes
179
329
let lock_token = self . lock ( & metadata_key) . await ?;
180
330
// use a closure to prevent locking forever caused by errors
@@ -189,7 +339,7 @@ impl crate::application::CoLink {
189
339
let chunk_paths_string = self . _check_chunk_paths_size ( chunk_paths) ?;
190
340
// update the metadata entry
191
341
let response = self
192
- . update_entry ( & metadata_key, & chunk_paths_string. into_bytes ( ) )
342
+ . update_entry ( & metadata_key, chunk_paths_string. as_bytes ( ) )
193
343
. await ?;
194
344
Ok :: < String , Error > ( response)
195
345
}
@@ -200,6 +350,12 @@ impl crate::application::CoLink {
200
350
201
351
#[ async_recursion]
202
352
pub ( crate ) async fn _delete_entry_chunk ( & self , key_name : & str ) -> Result < String , Error > {
353
+ if key_name. contains ( '$' ) {
354
+ self . _chunk_lock_compatibility_mode ( key_name) . await ?;
355
+ let res = self . _delete_chunks_compatibility_mode ( key_name) . await ;
356
+ self . _chunk_unlock_compatibility_mode ( key_name) . await ?;
357
+ return res;
358
+ }
203
359
let metadata_key = format ! ( "{}:chunk_metadata" , key_name) ;
204
360
let lock_token = self . lock ( & metadata_key) . await ?;
205
361
let res = self . delete_entry ( & metadata_key) . await ;
0 commit comments