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 ;
5
5
use std:: path:: Path ;
6
6
use std:: sync:: { Arc , Mutex } ;
7
7
8
8
use crate :: checksum;
9
+ use crate :: dump_utils:: * ;
9
10
use crate :: io_engine:: { AsyncIoEngine , Block , IoEngine , SyncIoEngine } ;
10
11
use crate :: pdata:: btree:: { self , * } ;
11
12
use crate :: pdata:: btree_walker:: * ;
@@ -153,58 +154,49 @@ pub struct ThinDumpOptions<'a> {
153
154
pub overrides : SuperblockOverrides ,
154
155
}
155
156
156
- struct Context {
157
+ struct ThinDumpContext {
157
158
report : Arc < Report > ,
158
159
engine : Arc < dyn IoEngine + Send + Sync > ,
159
160
}
160
161
161
- fn mk_context ( opts : & ThinDumpOptions ) -> Result < Context > {
162
+ fn mk_context ( opts : & ThinDumpOptions ) -> Result < ThinDumpContext > {
162
163
let engine: Arc < dyn IoEngine + Send + Sync > = if opts. async_io {
163
164
Arc :: new ( AsyncIoEngine :: new ( opts. input , MAX_CONCURRENT_IO , false ) ?)
164
165
} else {
165
166
let nr_threads = std:: cmp:: max ( 8 , num_cpus:: get ( ) * 2 ) ;
166
167
Arc :: new ( SyncIoEngine :: new ( opts. input , nr_threads, false ) ?)
167
168
} ;
168
169
169
- Ok ( Context {
170
+ Ok ( ThinDumpContext {
170
171
report : opts. report . clone ( ) ,
171
172
engine,
172
173
} )
173
174
}
174
175
175
176
//------------------------------------------
176
177
177
- fn emit_leaf ( v : & mut MappingVisitor , b : & Block ) -> Result < ( ) > {
178
+ fn emit_leaf ( v : & MappingVisitor , b : & Block ) -> Result < ( ) > {
178
179
use Node :: * ;
179
180
let path = Vec :: new ( ) ;
180
181
let kr = KeyRange :: new ( ) ;
181
182
182
183
let bt = checksum:: metadata_block_type ( b. get_data ( ) ) ;
183
184
if bt != checksum:: BT :: NODE {
184
- return Err ( anyhow ! ( format!(
185
- "checksum failed for node {}, {:?}" ,
186
- b. loc, bt
187
- ) ) ) ;
185
+ return Err ( anyhow ! ( "checksum failed for node {}, {:?}" , b. loc, bt) ) ;
188
186
}
189
187
190
188
let node = unpack_node :: < BlockTime > ( & path, b. get_data ( ) , true , true ) ?;
191
189
192
190
match node {
193
- Internal { .. } => {
194
- return Err ( anyhow ! ( "not a leaf" ) ) ;
195
- }
191
+ Internal { .. } => Err ( anyhow ! ( "block {} is not a leaf" , b. loc) ) ,
196
192
Leaf {
197
193
header,
198
194
keys,
199
195
values,
200
- } => {
201
- if let Err ( _e) = v. visit ( & path, & kr, & header, & keys, & values) {
202
- return Err ( anyhow ! ( "couldn't emit leaf node" ) ) ;
203
- }
204
- }
196
+ } => v
197
+ . visit ( & path, & kr, & header, & keys, & values)
198
+ . context ( OutputError ) ,
205
199
}
206
-
207
- Ok ( ( ) )
208
200
}
209
201
210
202
fn read_for < T > ( engine : Arc < dyn IoEngine > , blocks : & [ u64 ] , mut t : T ) -> Result < ( ) >
@@ -216,22 +208,27 @@ where
216
208
. read_many ( cs)
217
209
. map_err ( |_e| anyhow ! ( "read_many failed" ) ) ?
218
210
{
219
- t ( b. map_err ( |_e| anyhow ! ( "read of individual block failed" ) ) ?) ?;
211
+ let blk = b. map_err ( |_e| anyhow ! ( "read of individual block failed" ) ) ?;
212
+ t ( blk) ?;
220
213
}
221
214
}
222
215
223
216
Ok ( ( ) )
224
217
}
225
218
226
- fn emit_leaves ( engine : Arc < dyn IoEngine > , out : & mut dyn MetadataVisitor , ls : & [ u64 ] ) -> Result < ( ) > {
227
- let mut v = MappingVisitor :: new ( out) ;
219
+ fn emit_leaves (
220
+ engine : Arc < dyn IoEngine > ,
221
+ out : & mut dyn MetadataVisitor ,
222
+ leaves : & [ u64 ] ,
223
+ ) -> Result < ( ) > {
224
+ let v = MappingVisitor :: new ( out) ;
228
225
let proc = |b| {
229
- emit_leaf ( & mut v, & b) ?;
226
+ emit_leaf ( & v, & b) ?;
230
227
Ok ( ( ) )
231
228
} ;
232
229
233
- read_for ( engine, ls , proc) ?;
234
- v. end_walk ( ) . map_err ( |_| anyhow ! ( "failed to emit leaves" ) )
230
+ read_for ( engine, leaves , proc) ?;
231
+ v. end_walk ( ) . context ( OutputError )
235
232
}
236
233
237
234
fn emit_entries (
@@ -252,7 +249,7 @@ fn emit_entries(
252
249
leaves. clear ( ) ;
253
250
}
254
251
let str = format ! ( "{}" , id) ;
255
- out. ref_shared ( & str) ?;
252
+ out. ref_shared ( & str) . context ( OutputError ) ?;
256
253
}
257
254
}
258
255
}
@@ -281,12 +278,13 @@ pub fn dump_metadata(
281
278
nr_data_blocks : data_root. nr_blocks ,
282
279
metadata_snap : None ,
283
280
} ;
284
- out. superblock_b ( & out_sb) ?;
281
+ out. superblock_b ( & out_sb) . context ( OutputError ) ?;
285
282
286
283
for d in & md. defs {
287
- out. def_shared_b ( & format ! ( "{}" , d. def_id) ) ?;
284
+ out. def_shared_b ( & format ! ( "{}" , d. def_id) )
285
+ . context ( OutputError ) ?;
288
286
emit_entries ( engine. clone ( ) , out, & d. map . entries ) ?;
289
- out. def_shared_e ( ) ?;
287
+ out. def_shared_e ( ) . context ( OutputError ) ?;
290
288
}
291
289
292
290
for dev in & md. devs {
@@ -297,12 +295,12 @@ pub fn dump_metadata(
297
295
creation_time : dev. detail . creation_time ,
298
296
snap_time : dev. detail . snapshotted_time ,
299
297
} ;
300
- out. device_b ( & device) ?;
298
+ out. device_b ( & device) . context ( OutputError ) ?;
301
299
emit_entries ( engine. clone ( ) , out, & dev. map . entries ) ?;
302
- out. device_e ( ) ?;
300
+ out. device_e ( ) . context ( OutputError ) ?;
303
301
}
304
- out. superblock_e ( ) ?;
305
- out. eof ( ) ?;
302
+ out. superblock_e ( ) . context ( OutputError ) ?;
303
+ out. eof ( ) . context ( OutputError ) ?;
306
304
307
305
Ok ( ( ) )
308
306
}
@@ -324,11 +322,13 @@ pub fn dump(opts: ThinDumpOptions) -> Result<()> {
324
322
read_superblock ( ctx. engine . as_ref ( ) , SUPERBLOCK_LOCATION )
325
323
. and_then ( |sb| sb. overrides ( & opts. overrides ) ) ?
326
324
} ;
325
+
327
326
let md = build_metadata ( ctx. engine . clone ( ) , & sb) ?;
328
327
let md = optimise_metadata ( md) ?;
329
328
330
329
let writer: Box < dyn Write > = if opts. output . is_some ( ) {
331
- Box :: new ( BufWriter :: new ( File :: create ( opts. output . unwrap ( ) ) ?) )
330
+ let f = File :: create ( opts. output . unwrap ( ) ) . context ( OutputError ) ?;
331
+ Box :: new ( BufWriter :: new ( f) )
332
332
} else {
333
333
Box :: new ( BufWriter :: new ( std:: io:: stdout ( ) ) )
334
334
} ;
0 commit comments