CBufferedFile: convert into a non-refcounted RAII wrapper

- it now takes over the passed file descriptor and closes it in the
  destructor
- this fixes a leak in LoadExternalBlockFile(), where an exception could
  cause the file to not getting closed

- disallow copies (like recently added for CAutoFile)
- make nType and nVersion private
This commit is contained in:
Philip Kaufmann 2014-09-25 08:53:43 +02:00
parent 00eef5d6e9
commit c9fb27da0a
2 changed files with 22 additions and 10 deletions

View File

@ -3084,6 +3084,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
int nLoaded = 0; int nLoaded = 0;
try { try {
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
uint64_t nStartByte = 0; uint64_t nStartByte = 0;
if (dbp) { if (dbp) {
@ -3140,7 +3141,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what()); LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what());
} }
} }
fclose(fileIn);
} catch(std::runtime_error &e) { } catch(std::runtime_error &e) {
AbortNode(_("Error: system error: ") + e.what()); AbortNode(_("Error: system error: ") + e.what());
} }

View File

@ -1256,12 +1256,18 @@ public:
} }
}; };
/** Wrapper around a FILE* that implements a ring buffer to /** Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to
* deserialize from. It guarantees the ability to rewind * deserialize from. It guarantees the ability to rewind a given number of bytes. */
* a given number of bytes. */
class CBufferedFile class CBufferedFile
{ {
private: private:
// Disallow copies
CBufferedFile(const CBufferedFile&);
CBufferedFile& operator=(const CBufferedFile&);
int nType;
int nVersion;
FILE *src; // source file FILE *src; // source file
uint64_t nSrcPos; // how many bytes have been read from source uint64_t nSrcPos; // how many bytes have been read from source
uint64_t nReadPos; // how many bytes have been read from this uint64_t nReadPos; // how many bytes have been read from this
@ -1289,12 +1295,18 @@ protected:
} }
public: public:
int nType;
int nVersion;
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
nType(nTypeIn), nVersion(nVersionIn) { {
src = fileIn;
nType = nTypeIn;
nVersion = nVersionIn;
}
~CBufferedFile()
{
if (src)
fclose(src);
} }
// check whether we're at the end of the source file // check whether we're at the end of the source file