mmap.cpp: also added createTemporary() support
parent
4bae47db4c
commit
c97ea5f1cb
|
@ -103,7 +103,12 @@ public:
|
||||||
//! @{ \name Miscellaneous
|
//! @{ \name Miscellaneous
|
||||||
// =============================================================
|
// =============================================================
|
||||||
|
|
||||||
/// Create a temporary file and return an associated FileStream
|
/**
|
||||||
|
* \brief Create a temporary file and return an associated FileStream
|
||||||
|
*
|
||||||
|
* \remark When closing the file stream, the file is automatically
|
||||||
|
* deleted.
|
||||||
|
*/
|
||||||
static ref<FileStream> createTemporary();
|
static ref<FileStream> createTemporary();
|
||||||
|
|
||||||
/// Initialize the file I/O layer (unicode conversions etc.)
|
/// Initialize the file I/O layer (unicode conversions etc.)
|
||||||
|
|
|
@ -54,14 +54,28 @@ public:
|
||||||
*/
|
*/
|
||||||
void resize(size_t size);
|
void resize(size_t size);
|
||||||
|
|
||||||
|
/// Return the associated filename
|
||||||
|
const fs::path &getFilename() const;
|
||||||
|
|
||||||
/// Return whether the mapped memory region is read-only
|
/// Return whether the mapped memory region is read-only
|
||||||
bool isReadOnly() const;
|
bool isReadOnly() const;
|
||||||
|
|
||||||
/// Return a string representation
|
/// Return a string representation
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Create a temporary memory-mapped file
|
||||||
|
*
|
||||||
|
* \remark When closing the mapping, the file is
|
||||||
|
* automatically deleted.
|
||||||
|
*/
|
||||||
|
static ref<MemoryMappedFile> createTemporary(size_t size);
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
protected:
|
protected:
|
||||||
|
/// Internal constructor
|
||||||
|
MemoryMappedFile();
|
||||||
|
|
||||||
/// Release all resources
|
/// Release all resources
|
||||||
virtual ~MemoryMappedFile();
|
virtual ~MemoryMappedFile();
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -53,7 +53,6 @@ FileStream::FileStream(const fs::path &path, EFileMode mode)
|
||||||
open(path, mode);
|
open(path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FileStream::~FileStream() {
|
FileStream::~FileStream() {
|
||||||
if (d->file != 0)
|
if (d->file != 0)
|
||||||
close();
|
close();
|
||||||
|
@ -189,7 +188,6 @@ void FileStream::close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FileStream::remove() {
|
void FileStream::remove() {
|
||||||
close();
|
close();
|
||||||
Log(EDebug, "Removing \"%s\"", d->path.string().c_str());
|
Log(EDebug, "Removing \"%s\"", d->path.string().c_str());
|
||||||
|
|
|
@ -18,9 +18,10 @@ struct MemoryMappedFile::MemoryMappedFilePrivate {
|
||||||
size_t size;
|
size_t size;
|
||||||
void *data;
|
void *data;
|
||||||
bool readOnly;
|
bool readOnly;
|
||||||
|
bool temp;
|
||||||
|
|
||||||
MemoryMappedFilePrivate(const fs::path & f, size_t s = 0)
|
MemoryMappedFilePrivate(const fs::path &f = "", size_t s = 0)
|
||||||
: filename(f), size(s), data(NULL), readOnly(false) {}
|
: filename(f), size(s), data(NULL), readOnly(false), temp(false) {}
|
||||||
|
|
||||||
void create() {
|
void create() {
|
||||||
#if defined(__LINUX__) || defined(__OSX__)
|
#if defined(__LINUX__) || defined(__OSX__)
|
||||||
|
@ -57,10 +58,69 @@ struct MemoryMappedFile::MemoryMappedFilePrivate {
|
||||||
readOnly = false;
|
readOnly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createTemp() {
|
||||||
|
readOnly = false;
|
||||||
|
temp = true;
|
||||||
|
|
||||||
|
#if defined(__LINUX__) || defined(__OSX__)
|
||||||
|
char *path = strdup("/tmp/mitsuba_XXXXXX");
|
||||||
|
int fd = mkstemp(path);
|
||||||
|
if (fd == -1)
|
||||||
|
SLog(EError, "Unable to create temporary file (1): %s", strerror(errno));
|
||||||
|
filename = path;
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
int result = lseek(fd, size-1, SEEK_SET);
|
||||||
|
if (result == -1)
|
||||||
|
Log(EError, "Could not set file size of \"%s\"!", filename.string().c_str());
|
||||||
|
result = write(fd, "", 1);
|
||||||
|
if (result != 1)
|
||||||
|
Log(EError, "Could not write to \"%s\"!", filename.string().c_str());
|
||||||
|
|
||||||
|
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (data == NULL)
|
||||||
|
Log(EError, "Could not map \"%s\" to memory!", filename.string().c_str());
|
||||||
|
|
||||||
|
if (close(fd) != 0)
|
||||||
|
Log(EError, "close(): unable to close file!");
|
||||||
|
#elif defined(__WINDOWS__)
|
||||||
|
WCHAR tempPath[MAX_PATH];
|
||||||
|
WCHAR filename[MAX_PATH];
|
||||||
|
|
||||||
|
unsigned int ret = GetTempPathW(MAX_PATH, tempPath);
|
||||||
|
if (ret == 0 || ret > MAX_PATH)
|
||||||
|
SLog(EError, "GetTempPath failed(): %s", lastErrorText().c_str());
|
||||||
|
|
||||||
|
ret = GetTempFileNameW(tempPath, TEXT("mitsuba"), 0, filename);
|
||||||
|
if (ret == 0)
|
||||||
|
SLog(EError, "GetTempFileName failed(): %s", lastErrorText().c_str());
|
||||||
|
|
||||||
|
file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
|
SLog(EError, "Error while trying to create temporary file \"%s\": %s",
|
||||||
|
d->path.string().c_str(), lastErrorText().c_str());
|
||||||
|
|
||||||
|
filename = fs::path(filename);
|
||||||
|
|
||||||
|
fileMapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0,
|
||||||
|
static_cast<DWORD>(size), NULL);
|
||||||
|
if (fileMapping == NULL)
|
||||||
|
Log(EError, "CreateFileMapping: Could not map \"%s\" to memory: %s",
|
||||||
|
filename.string().c_str(), lastErrorText().c_str());
|
||||||
|
data = (void *) MapViewOfFile(fileMapping, FILE_MAP_WRITE, 0, 0, 0);
|
||||||
|
if (data == NULL)
|
||||||
|
Log(EError, "MapViewOfFile: Could not map \"%s\" to memory: %s",
|
||||||
|
filename.string().c_str(), lastErrorText().c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void map() {
|
void map() {
|
||||||
if (!fs::exists(filename))
|
if (!fs::exists(filename))
|
||||||
Log(EError, "The file \"%s\" does not exist!", filename.string().c_str());
|
Log(EError, "The file \"%s\" does not exist!", filename.string().c_str());
|
||||||
size = (size_t) fs::file_size(filename);
|
size = (size_t) fs::file_size(filename);
|
||||||
|
|
||||||
#if defined(__LINUX__) || defined(__OSX__)
|
#if defined(__LINUX__) || defined(__OSX__)
|
||||||
int fd = open(filename.string().c_str(), readOnly ? O_RDONLY : O_RDWR);
|
int fd = open(filename.string().c_str(), readOnly ? O_RDONLY : O_RDWR);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
|
@ -91,10 +151,19 @@ struct MemoryMappedFile::MemoryMappedFilePrivate {
|
||||||
void unmap() {
|
void unmap() {
|
||||||
SLog(ETrace, "Unmapping \"%s\" from memory",
|
SLog(ETrace, "Unmapping \"%s\" from memory",
|
||||||
filename.string().c_str());
|
filename.string().c_str());
|
||||||
|
|
||||||
#if defined(__LINUX__) || defined(__OSX__)
|
#if defined(__LINUX__) || defined(__OSX__)
|
||||||
|
if (temp) {
|
||||||
|
/* Temporary file that will be deleted in any case:
|
||||||
|
invalidate dirty pages to avoid a costly flush to disk */
|
||||||
|
int retval = msync(data, size, MS_INVALIDATE);
|
||||||
|
if (retval != 0)
|
||||||
|
Log(EError, "munmap(): unable to unmap memory: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
int retval = munmap(data, size);
|
int retval = munmap(data, size);
|
||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
Log(EError, "munmap(): unable to unmap memory!");
|
Log(EError, "munmap(): unable to unmap memory: %s", strerror(errno));
|
||||||
#elif defined(__WINDOWS__)
|
#elif defined(__WINDOWS__)
|
||||||
if (!UnmapViewOfFile(data))
|
if (!UnmapViewOfFile(data))
|
||||||
Log(EError, "UnmapViewOfFile(): unable to unmap memory: %s", lastErrorText().c_str());
|
Log(EError, "UnmapViewOfFile(): unable to unmap memory: %s", lastErrorText().c_str());
|
||||||
|
@ -103,11 +172,23 @@ struct MemoryMappedFile::MemoryMappedFilePrivate {
|
||||||
if (!CloseHandle(file))
|
if (!CloseHandle(file))
|
||||||
Log(EError, "CloseHandle(): unable to close file: %s", lastErrorText().c_str());
|
Log(EError, "CloseHandle(): unable to close file: %s", lastErrorText().c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (temp) {
|
||||||
|
try {
|
||||||
|
fs::remove(filename);
|
||||||
|
} catch (...) {
|
||||||
|
Log(EWarn, "unmap(): Unable to delete file \"%s\"", filename.string().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data = NULL;
|
data = NULL;
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MemoryMappedFile::MemoryMappedFile()
|
||||||
|
: d(new MemoryMappedFilePrivate()) { }
|
||||||
|
|
||||||
MemoryMappedFile::MemoryMappedFile(const fs::path &filename, size_t size)
|
MemoryMappedFile::MemoryMappedFile(const fs::path &filename, size_t size)
|
||||||
: d(new MemoryMappedFilePrivate(filename, size)) {
|
: d(new MemoryMappedFilePrivate(filename, size)) {
|
||||||
SLog(ETrace, "Creating memory-mapped file \"%s\" (%s)..",
|
SLog(ETrace, "Creating memory-mapped file \"%s\" (%s)..",
|
||||||
|
@ -138,10 +219,13 @@ MemoryMappedFile::~MemoryMappedFile() {
|
||||||
void MemoryMappedFile::resize(size_t size) {
|
void MemoryMappedFile::resize(size_t size) {
|
||||||
if (!d->data)
|
if (!d->data)
|
||||||
Log(EError, "Internal error in MemoryMappedFile::resize()!");
|
Log(EError, "Internal error in MemoryMappedFile::resize()!");
|
||||||
|
bool temp = d->temp;
|
||||||
|
d->temp = false;
|
||||||
d->unmap();
|
d->unmap();
|
||||||
fs::resize_file(d->filename, size);
|
fs::resize_file(d->filename, size);
|
||||||
d->size = size;
|
d->size = size;
|
||||||
d->map();
|
d->map();
|
||||||
|
d->temp = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MemoryMappedFile::getData() {
|
void *MemoryMappedFile::getData() {
|
||||||
|
@ -161,6 +245,17 @@ bool MemoryMappedFile::isReadOnly() const {
|
||||||
return d->readOnly;
|
return d->readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fs::path &MemoryMappedFile::getFilename() const {
|
||||||
|
return d->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref<MemoryMappedFile> MemoryMappedFile::createTemporary(size_t size) {
|
||||||
|
ref<MemoryMappedFile> result = new MemoryMappedFile();
|
||||||
|
result->d->size = size;
|
||||||
|
result->d->createTemp();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::string MemoryMappedFile::toString() const {
|
std::string MemoryMappedFile::toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "MemoryMappedFile[filename=\""
|
oss << "MemoryMappedFile[filename=\""
|
||||||
|
|
Loading…
Reference in New Issue