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,56 +153,59 @@ 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
- fn emit_leaf ( v : & mut MappingVisitor , b : & Block ) -> Result < ( ) > {
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
+
187
+ fn emit_leaf ( v : & 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
- Internal { .. } => {
194
- return Err ( anyhow ! ( "not a leaf" ) ) ;
195
- }
200
+ Internal { .. } => Err ( anyhow ! ( "block {} is not a leaf" , b. loc) ) ,
196
201
Leaf {
197
202
header,
198
203
keys,
199
204
values,
200
- } => {
201
- v . visit ( & path, & kr, & header, & keys, & values) ? ;
202
- }
205
+ } => v
206
+ . visit ( & path, & kr, & header, & keys, & values)
207
+ . context ( OutputError ) ,
203
208
}
204
-
205
- Ok ( ( ) )
206
209
}
207
210
208
211
fn read_for < T > ( engine : Arc < dyn IoEngine > , blocks : & [ u64 ] , mut t : T ) -> Result < ( ) >
@@ -214,7 +217,8 @@ where
214
217
. read_many ( cs)
215
218
. map_err ( |_e| anyhow ! ( "read_many failed" ) ) ?
216
219
{
217
- t ( b. map_err ( |_e| anyhow ! ( "read of individual block failed" ) ) ?) ?;
220
+ let blk = b. map_err ( |_e| anyhow ! ( "read of individual block failed" ) ) ?;
221
+ t ( blk) ?;
218
222
}
219
223
}
220
224
@@ -226,15 +230,14 @@ fn emit_leaves(
226
230
out : & mut dyn MetadataVisitor ,
227
231
leaves : & [ u64 ] ,
228
232
) -> Result < ( ) > {
229
- let mut v = MappingVisitor :: new ( out) ;
233
+ let v = MappingVisitor :: new ( out) ;
230
234
let proc = |b| {
231
- emit_leaf ( & mut v, & b) ?;
235
+ emit_leaf ( & v, & b) ?;
232
236
Ok ( ( ) )
233
237
} ;
234
238
235
239
read_for ( engine, leaves, proc) ?;
236
- v. end_walk ( )
237
- . map_err ( |e| anyhow ! ( "failed to emit leaves: {}" , e) )
240
+ v. end_walk ( ) . context ( OutputError )
238
241
}
239
242
240
243
fn emit_entries (
@@ -255,7 +258,7 @@ fn emit_entries(
255
258
leaves. clear ( ) ;
256
259
}
257
260
let str = format ! ( "{}" , id) ;
258
- out. ref_shared ( & str) ?;
261
+ out. ref_shared ( & str) . context ( OutputError ) ?;
259
262
}
260
263
}
261
264
}
@@ -284,12 +287,13 @@ pub fn dump_metadata(
284
287
nr_data_blocks : data_root. nr_blocks ,
285
288
metadata_snap : None ,
286
289
} ;
287
- out. superblock_b ( & out_sb) ?;
290
+ out. superblock_b ( & out_sb) . context ( OutputError ) ?;
288
291
289
292
for d in & md. defs {
290
- out. def_shared_b ( & format ! ( "{}" , d. def_id) ) ?;
293
+ out. def_shared_b ( & format ! ( "{}" , d. def_id) )
294
+ . context ( OutputError ) ?;
291
295
emit_entries ( engine. clone ( ) , out, & d. map . entries ) ?;
292
- out. def_shared_e ( ) ?;
296
+ out. def_shared_e ( ) . context ( OutputError ) ?;
293
297
}
294
298
295
299
for dev in & md. devs {
@@ -300,12 +304,12 @@ pub fn dump_metadata(
300
304
creation_time : dev. detail . creation_time ,
301
305
snap_time : dev. detail . snapshotted_time ,
302
306
} ;
303
- out. device_b ( & device) ?;
307
+ out. device_b ( & device) . context ( OutputError ) ?;
304
308
emit_entries ( engine. clone ( ) , out, & dev. map . entries ) ?;
305
- out. device_e ( ) ?;
309
+ out. device_e ( ) . context ( OutputError ) ?;
306
310
}
307
- out. superblock_e ( ) ?;
308
- out. eof ( ) ?;
311
+ out. superblock_e ( ) . context ( OutputError ) ?;
312
+ out. eof ( ) . context ( OutputError ) ?;
309
313
310
314
Ok ( ( ) )
311
315
}
@@ -327,11 +331,13 @@ pub fn dump(opts: ThinDumpOptions) -> Result<()> {
327
331
read_superblock ( ctx. engine . as_ref ( ) , SUPERBLOCK_LOCATION )
328
332
. and_then ( |sb| sb. overrides ( & opts. overrides ) ) ?
329
333
} ;
334
+
330
335
let md = build_metadata ( ctx. engine . clone ( ) , & sb) ?;
331
336
let md = optimise_metadata ( md) ?;
332
337
333
338
let writer: Box < dyn Write > = if opts. output . is_some ( ) {
334
- Box :: new ( BufWriter :: new ( File :: create ( opts. output . unwrap ( ) ) ?) )
339
+ let f = File :: create ( opts. output . unwrap ( ) ) . context ( OutputError ) ?;
340
+ Box :: new ( BufWriter :: new ( f) )
335
341
} else {
336
342
Box :: new ( BufWriter :: new ( std:: io:: stdout ( ) ) )
337
343
} ;
0 commit comments