mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Add RandomAccessFile
This commit is contained in:
@@ -504,6 +504,176 @@ Result FileOutputStream::truncate()
|
||||
return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
RandomAccessFile::RandomAccessFile (int bufferSizeToUse) noexcept
|
||||
: fileHandle (nullptr)
|
||||
, currentPosition (0)
|
||||
, writeBuffer (bufferSizeToUse)
|
||||
{
|
||||
}
|
||||
|
||||
RandomAccessFile::~RandomAccessFile ()
|
||||
{
|
||||
close ();
|
||||
}
|
||||
|
||||
Result RandomAccessFile::open (File const& path, Mode mode)
|
||||
{
|
||||
close ();
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
if (path.exists())
|
||||
{
|
||||
int oflag;
|
||||
switch (mode)
|
||||
{
|
||||
case readOnly:
|
||||
oflag = O_RDONLY;
|
||||
break;
|
||||
|
||||
default:
|
||||
case readWRite:
|
||||
oflag = O_RDWR;
|
||||
break;
|
||||
};
|
||||
|
||||
const int f = ::open (path.getFullPathName().toUTF8(), oflag, 00644);
|
||||
|
||||
if (f != -1)
|
||||
{
|
||||
currentPosition = lseek (f, 0, SEEK_SET);
|
||||
|
||||
if (currentPosition >= 0)
|
||||
{
|
||||
file = path;
|
||||
fileHandle = fdToVoidPointer (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = getResultForErrno();
|
||||
::close (f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = getResultForErrno();
|
||||
}
|
||||
}
|
||||
else if (mode == readWrite)
|
||||
{
|
||||
const int f = open (file.getFullPathName().toUTF8(), O_RDWR + O_CREAT, 00644);
|
||||
|
||||
if (f != -1)
|
||||
{
|
||||
file = path;
|
||||
fileHandle = fdToVoidPointer (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = getResultForErrno();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// file doesn't exist and we're opening read-only
|
||||
Result::fail (String (strerror (ENOENT)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void RandomAccessFile::close ()
|
||||
{
|
||||
if (fileHandle != nullptr)
|
||||
{
|
||||
file = File::nonexistent ();
|
||||
::close (getFD (fileHandle));
|
||||
fileHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Result RandomAccessFile::setPosition (Offset newPosition)
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
off_t const actual = lseek (getFD (fileHandle), newPosition, SEEK_SET);
|
||||
|
||||
if (actual != newPosition)
|
||||
result = getResultForErrno();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::read (void* buffer, ByteCount numBytes, ByteCount* pActualAmount )
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
ssize_t amount = ::read (getFD (fileHandle), buffer, numBytes);
|
||||
|
||||
if (amount < 0)
|
||||
{
|
||||
result = getResultForErrno();
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
if (pActualAmount != nullptr)
|
||||
*pActualAmount = amount;
|
||||
|
||||
return (size_t) result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::write (void const* data, ByteCount numBytes, size_t* pActualAmount)
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
ssize_t const actual = ::write (getFD (fileHandle), data, numBytes);
|
||||
|
||||
if (actual == -1)
|
||||
{
|
||||
status = getResultForErrno();
|
||||
actual = 0;
|
||||
}
|
||||
|
||||
if (pActualAmount != nullptr)
|
||||
*pActualAmount = actual;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::truncate ()
|
||||
{
|
||||
flush();
|
||||
|
||||
return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition));
|
||||
}
|
||||
|
||||
void RandomAccessFile::flush ()
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
if (fileHandle != nullptr)
|
||||
{
|
||||
if (fsync (getFD (fileHandle)) == -1)
|
||||
status = getResultForErrno();
|
||||
|
||||
#if BEAST_ANDROID
|
||||
// This stuff tells the OS to asynchronously update the metadata
|
||||
// that the OS has cached aboud the file - this metadata is used
|
||||
// when the device is acting as a USB drive, and unless it's explicitly
|
||||
// refreshed, it'll get out of step with the real file.
|
||||
const LocalRef<jstring> t (javaString (file.getFullPathName()));
|
||||
android.activity.callVoidMethod (BeastAppActivity.scanFile, t.get());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
|
||||
{
|
||||
|
||||
@@ -307,6 +307,161 @@ Result FileOutputStream::truncate()
|
||||
: WindowsFileHelpers::getResultForLastError();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
Result RandomAccessFile::nativeOpen (File const& path, Mode mode)
|
||||
{
|
||||
bassert (! isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
DWORD dwDesiredAccess;
|
||||
switch (mode)
|
||||
{
|
||||
case readOnly:
|
||||
dwDesiredAccess = GENERIC_READ;
|
||||
break;
|
||||
|
||||
default:
|
||||
case readWrite:
|
||||
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
break;
|
||||
};
|
||||
|
||||
DWORD dwCreationDisposition;
|
||||
switch (mode)
|
||||
{
|
||||
case readOnly:
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
break;
|
||||
|
||||
default:
|
||||
case readWrite:
|
||||
dwCreationDisposition = OPEN_ALWAYS;
|
||||
break;
|
||||
};
|
||||
|
||||
HANDLE h = CreateFile (path.getFullPathName().toWideCharPointer(),
|
||||
dwDesiredAccess,
|
||||
FILE_SHARE_READ,
|
||||
0,
|
||||
dwCreationDisposition,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
file = path;
|
||||
fileHandle = h;
|
||||
|
||||
result = setPosition (0);
|
||||
|
||||
if (result.failed ())
|
||||
nativeClose ();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = WindowsFileHelpers::getResultForLastError();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void RandomAccessFile::nativeClose ()
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
CloseHandle ((HANDLE) fileHandle);
|
||||
|
||||
file = File::nonexistent ();
|
||||
fileHandle = nullptr;
|
||||
currentPosition = 0;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::nativeSetPosition (FileOffset newPosition)
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = newPosition;
|
||||
li.LowPart = SetFilePointer ((HANDLE) fileHandle,
|
||||
(LONG) li.LowPart,
|
||||
&li.HighPart,
|
||||
FILE_BEGIN);
|
||||
|
||||
if (li.LowPart != INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
currentPosition = li.QuadPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = WindowsFileHelpers::getResultForLastError();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::nativeRead (void* buffer, ByteCount numBytes, ByteCount* pActualAmount )
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
DWORD actualNum = 0;
|
||||
|
||||
if (! ReadFile ((HANDLE) fileHandle, buffer, (DWORD) numBytes, &actualNum, 0))
|
||||
result = WindowsFileHelpers::getResultForLastError();
|
||||
|
||||
if (pActualAmount != nullptr)
|
||||
*pActualAmount = actualNum;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::nativeWrite (void const* data, ByteCount numBytes, size_t* pActualAmount)
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
DWORD actualNum = 0;
|
||||
|
||||
if (! WriteFile ((HANDLE) fileHandle, data, (DWORD) numBytes, &actualNum, 0))
|
||||
result = WindowsFileHelpers::getResultForLastError();
|
||||
|
||||
if (pActualAmount != nullptr)
|
||||
*pActualAmount = actualNum;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::nativeTruncate ()
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
if (! SetEndOfFile ((HANDLE) fileHandle))
|
||||
result = WindowsFileHelpers::getResultForLastError();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result RandomAccessFile::nativeFlush ()
|
||||
{
|
||||
bassert (isOpen ());
|
||||
|
||||
Result result (Result::ok ());
|
||||
|
||||
if (! FlushFileBuffers ((HANDLE) fileHandle))
|
||||
result = WindowsFileHelpers::getResultForLastError();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user