Propagate file read errors to callers Instead of having the file reader process crash with a badmatch after a file:pread/3, send the result to to the caller, which will in turn get a badmatch error. The advantage of this is to get a much more meaningful stack trace (relative to the client).
Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/6e38856a Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/6e38856a Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/6e38856a Branch: refs/heads/COUCHDB-1342 Commit: 6e38856a0a7c2a2030208a7af62061673bd056f2 Parents: 4f7336e Author: Filipe David Borba Manana <[email protected]> Authored: Sun Jan 22 13:15:15 2012 +0000 Committer: Filipe David Borba Manana <[email protected]> Committed: Sun Jan 22 13:15:15 2012 +0000 ---------------------------------------------------------------------- src/couchdb/couch_file.erl | 42 +++++++++++++++++++++++++------------- 1 files changed, 27 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/6e38856a/src/couchdb/couch_file.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_file.erl b/src/couchdb/couch_file.erl index bb69004..6e08cca 100644 --- a/src/couchdb/couch_file.erl +++ b/src/couchdb/couch_file.erl @@ -132,16 +132,19 @@ pread_binary(Fd, Pos) -> pread_iolist(Fd, Pos) -> - case do_read_iolist(Fd, Pos) of + case try_read_iolist(Fd, Pos) of eof -> - flush(Fd), - do_read_iolist(Fd, Pos); + ok = flush(Fd), + try_read_iolist(Fd, Pos); + {unexpected_binary, _, _, _} -> + ok = flush(Fd), + try_read_iolist(Fd, Pos); Else -> Else end. -do_read_iolist(Fd, Pos) -> +try_read_iolist(Fd, Pos) -> case gen_server:call(Fd, {pread_iolist, Pos}, infinity) of {ok, _IoList} = Ok -> Ok; @@ -486,8 +489,16 @@ read_raw_iolist_int(ReadFd, Pos, Len) -> case file:pread(ReadFd, Pos, TotalBytes) of {ok, <<RawBin:TotalBytes/binary>>} -> {remove_block_prefixes(BlockOffset, RawBin), Pos + TotalBytes}; - eof -> - throw(eof) + {ok, RawBin} -> + UnexpectedBin = { + unexpected_binary, + {at, Pos}, + {wanted_bytes, TotalBytes}, + {got, byte_size(RawBin), RawBin} + }, + throw({read_error, UnexpectedBin}); + Else -> + throw({read_error, Else}) end. -spec extract_md5(iolist()) -> {binary(), iolist()}. @@ -664,13 +675,7 @@ write_header_blocks(Fd, Eof, Header) -> reader_loop(Fd) -> receive {read, Pos, From} -> - Result = try - read_iolist(Fd, Pos) - catch - throw:eof -> - eof - end, - gen_server:reply(From, Result), + gen_server:reply(From, read_iolist(Fd, Pos)), reader_loop(Fd); {find_header, Eof, From} -> gen_server:reply(From, find_header(Fd, Eof div ?SIZE_BLOCK)), @@ -681,9 +686,16 @@ reader_loop(Fd) -> end. --compile({inline, [read_iolist/2]}). - read_iolist(Fd, Pos) -> + try + do_read_iolist(Fd, Pos) + catch throw:{read_error, Error} -> + Error + end. + +-compile({inline, [do_read_iolist/2]}). + +do_read_iolist(Fd, Pos) -> {RawData, NextPos} = try % up to 8Kbs of read ahead read_raw_iolist_int(Fd, Pos, 2 * ?SIZE_BLOCK - (Pos rem ?SIZE_BLOCK))
