From 48d91cf4cc53e820dafa3c6d5efdf4e5a06c2c29 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 17 Jul 2019 12:36:11 +0200 Subject: [PATCH] Rio: remember read/write error conditions. --- src/rdb.c | 1 - src/rio.c | 4 ++++ src/rio.h | 33 ++++++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/rdb.c b/src/rdb.c index 5111b6b88..e94f2934a 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -2168,7 +2168,6 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) { eoferr: /* unexpected end of file is handled here with a fatal exit */ serverLog(LL_WARNING,"Short read or OOM loading DB. Unrecoverable error, aborting now."); rdbReportReadError("Unexpected EOF reading RDB file"); -err: return C_ERR; } diff --git a/src/rio.c b/src/rio.c index 5359bc3d6..bdbc5d0e9 100644 --- a/src/rio.c +++ b/src/rio.c @@ -92,6 +92,7 @@ static const rio rioBufferIO = { rioBufferFlush, NULL, /* update_checksum */ 0, /* current checksum */ + 0, /* flags */ 0, /* bytes read or written */ 0, /* read/write chunk size */ { { NULL, 0 } } /* union for io-specific vars */ @@ -145,6 +146,7 @@ static const rio rioFileIO = { rioFileFlush, NULL, /* update_checksum */ 0, /* current checksum */ + 0, /* flags */ 0, /* bytes read or written */ 0, /* read/write chunk size */ { { NULL, 0 } } /* union for io-specific vars */ @@ -239,6 +241,7 @@ static const rio rioFdIO = { rioFdFlush, NULL, /* update_checksum */ 0, /* current checksum */ + 0, /* flags */ 0, /* bytes read or written */ 0, /* read/write chunk size */ { { NULL, 0 } } /* union for io-specific vars */ @@ -374,6 +377,7 @@ static const rio rioFdsetIO = { rioFdsetFlush, NULL, /* update_checksum */ 0, /* current checksum */ + 0, /* flags */ 0, /* bytes read or written */ 0, /* read/write chunk size */ { { NULL, 0 } } /* union for io-specific vars */ diff --git a/src/rio.h b/src/rio.h index beea06888..66036b5bd 100644 --- a/src/rio.h +++ b/src/rio.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2009-2012, Pieter Noordhuis - * Copyright (c) 2009-2012, Salvatore Sanfilippo + * Copyright (c) 2009-2019, Salvatore Sanfilippo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,9 @@ #include #include "sds.h" +#define RIO_FLAG_READ_ERROR (1<<0) +#define RIO_FLAG_WRITE_ERROR (1<<1) + struct _rio { /* Backend functions. * Since this functions do not tolerate short writes or reads the return @@ -51,8 +54,8 @@ struct _rio { * computation. */ void (*update_cksum)(struct _rio *, const void *buf, size_t len); - /* The current checksum */ - uint64_t cksum; + /* The current checksum and flags (see RIO_FLAG_*) */ + uint64_t cksum, flags; /* number of bytes read or written */ size_t processed_bytes; @@ -102,8 +105,10 @@ static inline size_t rioWrite(rio *r, const void *buf, size_t len) { while (len) { size_t bytes_to_write = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len; if (r->update_cksum) r->update_cksum(r,buf,bytes_to_write); - if (r->write(r,buf,bytes_to_write) == 0) + if (r->write(r,buf,bytes_to_write) == 0) { + r->flags |= RIO_FLAG_WRITE_ERROR; return 0; + } buf = (char*)buf + bytes_to_write; len -= bytes_to_write; r->processed_bytes += bytes_to_write; @@ -114,8 +119,10 @@ static inline size_t rioWrite(rio *r, const void *buf, size_t len) { static inline size_t rioRead(rio *r, void *buf, size_t len) { while (len) { size_t bytes_to_read = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len; - if (r->read(r,buf,bytes_to_read) == 0) + if (r->read(r,buf,bytes_to_read) == 0) { + r->flags |= RIO_FLAG_READ_ERROR; return 0; + } if (r->update_cksum) r->update_cksum(r,buf,bytes_to_read); buf = (char*)buf + bytes_to_read; len -= bytes_to_read; @@ -132,6 +139,22 @@ static inline int rioFlush(rio *r) { return r->flush(r); } +/* This function allows to know if there was a read error in any past + * operation, since the rio stream was created or since the last call + * to rioClearError(). */ +static inline int rioGetReadError(rio *r) { + return (r->flags & RIO_FLAG_READ_ERROR) != 0; +} + +/* Like rioGetReadError() but for write errors. */ +static inline int rioGetWriteError(rio *r) { + return (r->flags & RIO_FLAG_READ_ERROR) != 0; +} + +static inline void rioClearErrors(rio *r) { + r->flags &= ~(RIO_FLAG_READ_ERROR|RIO_FLAG_WRITE_ERROR); +} + void rioInitWithFile(rio *r, FILE *fp); void rioInitWithBuffer(rio *r, sds s); void rioInitWithFd(rio *r, int fd, size_t read_limit);