Clean up RandomAccessFile

This commit is contained in:
Vinnie Falco
2013-07-20 15:01:36 -07:00
parent dc7035ed19
commit e36f027a9a
2 changed files with 17 additions and 119 deletions

View File

@@ -17,12 +17,9 @@
*/ */
//============================================================================== //==============================================================================
RandomAccessFile::RandomAccessFile (int bufferSizeToUse) noexcept RandomAccessFile::RandomAccessFile () noexcept
: fileHandle (nullptr) : fileHandle (nullptr)
, currentPosition (0) , currentPosition (0)
, bufferSize (bufferSizeToUse)
, bytesInBuffer (0)
, writeBuffer (bmax (bufferSizeToUse, 16)) // enforce minimum size of 16
{ {
} }
@@ -42,7 +39,6 @@ void RandomAccessFile::close ()
{ {
if (isOpen ()) if (isOpen ())
{ {
flushBuffer ();
nativeFlush (); nativeFlush ();
nativeClose (); nativeClose ();
} }
@@ -52,8 +48,6 @@ Result RandomAccessFile::setPosition (FileOffset newPosition)
{ {
if (newPosition != currentPosition) if (newPosition != currentPosition)
{ {
flushBuffer ();
// VFALCO NOTE I dislike return from the middle but // VFALCO NOTE I dislike return from the middle but
// Result::ok() is showing up in the profile // Result::ok() is showing up in the profile
// //
@@ -76,37 +70,10 @@ Result RandomAccessFile::write (const void* data, ByteCount numBytes, ByteCount*
ByteCount amountWritten = 0; ByteCount amountWritten = 0;
if (bytesInBuffer + numBytes < bufferSize) result = nativeWrite (data, numBytes, &amountWritten);
{
memcpy (writeBuffer + bytesInBuffer, data, numBytes);
bytesInBuffer += numBytes;
currentPosition += numBytes;
}
else
{
result = flushBuffer ();
if (result.wasOk ()) if (result.wasOk ())
{ currentPosition += amountWritten;
if (numBytes < bufferSize)
{
bassert (bytesInBuffer == 0);
memcpy (writeBuffer + bytesInBuffer, data, numBytes);
bytesInBuffer += numBytes;
currentPosition += numBytes;
}
else
{
ByteCount bytesWritten;
result = nativeWrite (data, numBytes, &bytesWritten);
if (result.wasOk ())
currentPosition += bytesWritten;
}
}
}
if (pActualAmount != nullptr) if (pActualAmount != nullptr)
*pActualAmount = amountWritten; *pActualAmount = amountWritten;
@@ -126,27 +93,7 @@ Result RandomAccessFile::truncate ()
Result RandomAccessFile::flush () Result RandomAccessFile::flush ()
{ {
Result result = flushBuffer (); return nativeFlush ();
if (result.wasOk ())
result = nativeFlush ();
return result;
}
Result RandomAccessFile::flushBuffer ()
{
bassert (isOpen ());
Result result (Result::ok ());
if (bytesInBuffer > 0)
{
result = nativeWrite (writeBuffer, bytesInBuffer);
bytesInBuffer = 0;
}
return result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -158,6 +105,11 @@ public:
{ {
} }
enum
{
maxPayload = 8192
};
/* For this test we will create a file which consists of a fixed /* For this test we will create a file which consists of a fixed
number of variable length records. Each record is numbered sequentially number of variable length records. Each record is numbered sequentially
starting at 0. To calculate the position of each record we first build starting at 0. To calculate the position of each record we first build
@@ -260,15 +212,13 @@ public:
} }
// Perform the test at the given buffer size. // Perform the test at the given buffer size.
void testFile (int const numRecords, int const bufferSize) void testFile (int const numRecords)
{ {
using namespace UnitTestUtilities; using namespace UnitTestUtilities;
int const seedValue = 50; int const seedValue = 50;
beginTest (String ("numRecords=") + String (numRecords) + ", bufferSize=" + String (bufferSize)); beginTest (String ("numRecords=") + String (numRecords));
int const maxPayload = bmax (1000, bufferSize * 2);
// Calculate the path // Calculate the path
File const path (File::createTempFile ("RandomAccessFile")); File const path (File::createTempFile ("RandomAccessFile"));
@@ -281,7 +231,7 @@ public:
{ {
// Create the file // Create the file
RandomAccessFile file (bufferSize); RandomAccessFile file;
result = file.open (path, RandomAccessFile::readWrite); result = file.open (path, RandomAccessFile::readWrite);
expect (result.wasOk (), "Should be ok"); expect (result.wasOk (), "Should be ok");
@@ -300,7 +250,7 @@ public:
if (result.wasOk ()) if (result.wasOk ())
{ {
// Re-open the file in read only mode // Re-open the file in read only mode
RandomAccessFile file (bufferSize); RandomAccessFile file;
result = file.open (path, RandomAccessFile::readOnly); result = file.open (path, RandomAccessFile::readOnly);
expect (result.wasOk (), "Should be ok"); expect (result.wasOk (), "Should be ok");
@@ -313,11 +263,7 @@ public:
void runTest () void runTest ()
{ {
int const numRecords = 1000; testFile (10000);
testFile (numRecords, 0);
testFile (numRecords, 1000);
testFile (numRecords, 10000);
} }
private: private:

View File

@@ -3,10 +3,6 @@
This file is part of Beast: https://github.com/vinniefalco/Beast This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com> Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
@@ -34,10 +30,6 @@
provided for obtaining an input or output stream which will work with provided for obtaining an input or output stream which will work with
the file. the file.
Writes are batched using an internal buffer. The buffer is flushed when
it fills, the current position is manually changed, or the file
is closed. It is also possible to explicitly flush the buffer.
@note All files are opened in binary mode. No text newline conversions @note All files are opened in binary mode. No text newline conversions
are performed. are performed.
@@ -76,7 +68,7 @@ public:
@see open, isOpen @see open, isOpen
*/ */
explicit RandomAccessFile (int bufferSizeToUse = 16384) noexcept; RandomAccessFile () noexcept;
/** Destroy the file object. /** Destroy the file object.
@@ -182,12 +174,11 @@ public:
//============================================================================== //==============================================================================
private: private:
Result flushBuffer ();
// Some of these these methods are implemented natively on // Some of these these methods are implemented natively on
// the corresponding platform. // the corresponding platform.
// //
// See beast_posix_SharedCode.h and beast_win32_Files.cpp // See beast_posix_SharedCode.h and beast_win32_Files.cpp
//
Result nativeOpen (File const& path, Mode mode); Result nativeOpen (File const& path, Mode mode);
void nativeClose (); void nativeClose ();
Result nativeSetPosition (FileOffset newPosition); Result nativeSetPosition (FileOffset newPosition);
@@ -200,45 +191,6 @@ private:
File file; File file;
void* fileHandle; void* fileHandle;
FileOffset currentPosition; FileOffset currentPosition;
ByteCount const bufferSize;
ByteCount bytesInBuffer;
HeapBlock <char> writeBuffer;
};
class BEAST_API RandomAccessFileInputStream : public InputStream
{
public:
explicit RandomAccessFileInputStream (RandomAccessFile& file) : m_file (file) { }
int64 getTotalLength() { return m_file.getFile ().getSize (); }
bool isExhausted() { return getPosition () == getTotalLength (); }
int read (void* destBuffer, int maxBytesToRead)
{
size_t actualBytes = 0;
m_file.read (destBuffer, maxBytesToRead, &actualBytes);
return actualBytes;
}
int64 getPosition() { return m_file.getPosition (); }
bool setPosition (int64 newPosition) { return m_file.setPosition (newPosition); }
void skipNextBytes (int64 numBytesToSkip) { m_file.setPosition (getPosition () + numBytesToSkip); }
private:
RandomAccessFile& m_file;
};
class BEAST_API RandomAccessFileOutputStream : public OutputStream
{
public:
explicit RandomAccessFileOutputStream (RandomAccessFile& file) : m_file (file) { }
void flush() { m_file.flush (); }
int64 getPosition() { return m_file.getPosition (); }
bool setPosition (int64 newPosition) { return m_file.setPosition (newPosition); }
bool write (const void* dataToWrite, size_t numberOfBytes) { return m_file.write (dataToWrite, numberOfBytes); }
private:
RandomAccessFile& m_file;
}; };
#endif #endif