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