1
- use anyhow:: { anyhow, Result } ;
1
+ use anyhow:: { anyhow, Context , Result } ;
2
2
use std:: fs:: File ;
3
3
use std:: io:: BufWriter ;
4
4
use std:: io:: Write ;
@@ -153,52 +153,60 @@ pub struct ThinDumpOptions<'a> {
153
153
pub overrides : SuperblockOverrides ,
154
154
}
155
155
156
- struct Context {
156
+ struct ThinDumpContext {
157
157
report : Arc < Report > ,
158
158
engine : Arc < dyn IoEngine + Send + Sync > ,
159
159
}
160
160
161
- fn mk_context ( opts : & ThinDumpOptions ) -> Result < Context > {
161
+ fn mk_context ( opts : & ThinDumpOptions ) -> Result < ThinDumpContext > {
162
162
let engine: Arc < dyn IoEngine + Send + Sync > = if opts. async_io {
163
163
Arc :: new ( AsyncIoEngine :: new ( opts. input , MAX_CONCURRENT_IO , false ) ?)
164
164
} else {
165
165
let nr_threads = std:: cmp:: max ( 8 , num_cpus:: get ( ) * 2 ) ;
166
166
Arc :: new ( SyncIoEngine :: new ( opts. input , nr_threads, false ) ?)
167
167
} ;
168
168
169
- Ok ( Context {
169
+ Ok ( ThinDumpContext {
170
170
report : opts. report . clone ( ) ,
171
171
engine,
172
172
} )
173
173
}
174
174
175
175
//------------------------------------------
176
176
177
+ // a wrapper for callers to indicate the error type
178
+ #[ derive( Debug ) ]
179
+ pub struct OutputError ;
180
+
181
+ impl std:: fmt:: Display for OutputError {
182
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
183
+ write ! ( f, "output error" )
184
+ }
185
+ }
186
+
177
187
fn emit_leaf ( v : & mut MappingVisitor , b : & Block ) -> Result < ( ) > {
178
188
use Node :: * ;
179
189
let path = Vec :: new ( ) ;
180
190
let kr = KeyRange :: new ( ) ;
181
191
182
192
let bt = checksum:: metadata_block_type ( b. get_data ( ) ) ;
183
193
if bt != checksum:: BT :: NODE {
184
- return Err ( anyhow ! ( format!(
185
- "checksum failed for node {}, {:?}" ,
186
- b. loc, bt
187
- ) ) ) ;
194
+ return Err ( anyhow ! ( "checksum failed for node {}, {:?}" , b. loc, bt) ) ;
188
195
}
189
196
190
197
let node = unpack_node :: < BlockTime > ( & path, b. get_data ( ) , true , true ) ?;
191
198
192
199
match node {
193
200
Internal { .. } => {
194
- return Err ( anyhow ! ( "not a leaf" ) ) ;
201
+ return Err ( anyhow ! ( "block {} is not a leaf" , b . loc ) ) ;
195
202
}
196
203
Leaf {
197
204
header,
198
205
keys,
199
206
values,
200
207
} => {
201
- v. visit ( & path, & kr, & header, & keys, & values) ?;
208
+ v. visit ( & path, & kr, & header, & keys, & values)
209
+ . map_err ( |e| anyhow:: Error :: from ( e) . context ( OutputError ) ) ?;
202
210
}
203
211
}
204
212
@@ -214,7 +222,8 @@ where
214
222
. read_many ( cs)
215
223
. map_err ( |_e| anyhow ! ( "read_many failed" ) ) ?
216
224
{
217
- t ( b. map_err ( |_e| anyhow ! ( "read of individual block failed" ) ) ?) ?;
225
+ let blk = b. map_err ( |_e| anyhow ! ( "read of individual block failed" ) ) ?;
226
+ t ( blk) ?;
218
227
}
219
228
}
220
229
@@ -234,7 +243,7 @@ fn emit_leaves(
234
243
235
244
read_for ( engine, leaves, proc) ?;
236
245
v. end_walk ( )
237
- . map_err ( |e| anyhow ! ( "failed to emit leaves: {}" , e ) )
246
+ . map_err ( |e| anyhow:: Error :: from ( e ) . context ( OutputError ) )
238
247
}
239
248
240
249
fn emit_entries (
@@ -255,7 +264,7 @@ fn emit_entries(
255
264
leaves. clear ( ) ;
256
265
}
257
266
let str = format ! ( "{}" , id) ;
258
- out. ref_shared ( & str) ?;
267
+ out. ref_shared ( & str) . context ( OutputError ) ?;
259
268
}
260
269
}
261
270
}
@@ -284,12 +293,13 @@ pub fn dump_metadata(
284
293
nr_data_blocks : data_root. nr_blocks ,
285
294
metadata_snap : None ,
286
295
} ;
287
- out. superblock_b ( & out_sb) ?;
296
+ out. superblock_b ( & out_sb) . context ( OutputError ) ?;
288
297
289
298
for d in & md. defs {
290
- out. def_shared_b ( & format ! ( "{}" , d. def_id) ) ?;
299
+ out. def_shared_b ( & format ! ( "{}" , d. def_id) )
300
+ . context ( OutputError ) ?;
291
301
emit_entries ( engine. clone ( ) , out, & d. map . entries ) ?;
292
- out. def_shared_e ( ) ?;
302
+ out. def_shared_e ( ) . context ( OutputError ) ?;
293
303
}
294
304
295
305
for dev in & md. devs {
@@ -300,12 +310,12 @@ pub fn dump_metadata(
300
310
creation_time : dev. detail . creation_time ,
301
311
snap_time : dev. detail . snapshotted_time ,
302
312
} ;
303
- out. device_b ( & device) ?;
313
+ out. device_b ( & device) . context ( OutputError ) ?;
304
314
emit_entries ( engine. clone ( ) , out, & dev. map . entries ) ?;
305
- out. device_e ( ) ?;
315
+ out. device_e ( ) . context ( OutputError ) ?;
306
316
}
307
- out. superblock_e ( ) ?;
308
- out. eof ( ) ?;
317
+ out. superblock_e ( ) . context ( OutputError ) ?;
318
+ out. eof ( ) . context ( OutputError ) ?;
309
319
310
320
Ok ( ( ) )
311
321
}
@@ -327,11 +337,15 @@ pub fn dump(opts: ThinDumpOptions) -> Result<()> {
327
337
read_superblock ( ctx. engine . as_ref ( ) , SUPERBLOCK_LOCATION )
328
338
. and_then ( |sb| sb. overrides ( & opts. overrides ) ) ?
329
339
} ;
340
+
330
341
let md = build_metadata ( ctx. engine . clone ( ) , & sb) ?;
331
342
let md = optimise_metadata ( md) ?;
332
343
333
344
let writer: Box < dyn Write > = if opts. output . is_some ( ) {
334
- Box :: new ( BufWriter :: new ( File :: create ( opts. output . unwrap ( ) ) ?) )
345
+ Box :: new ( BufWriter :: new (
346
+ File :: create ( opts. output . unwrap ( ) )
347
+ . map_err ( |e| anyhow:: Error :: from ( e) . context ( OutputError ) ) ?,
348
+ ) )
335
349
} else {
336
350
Box :: new ( BufWriter :: new ( std:: io:: stdout ( ) ) )
337
351
} ;
0 commit comments